home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 544b.lha / 4D Navigator / 4d.c < prev    next >
C/C++ Source or Header  |  1991-09-06  |  57KB  |  2,334 lines

  1. /* 4D Navigator   ©1991, Jerry D. Hedden, All Rights Reserved
  2.  
  3. The 4D Navigator program, source code, documenation, and icon imagery are
  4. freely redistributable, but may not be modified in any way, or used in part
  5. or in whole without the express written consent of the author.    Images
  6. generated by the 4D Navigator program may be used for any purpose provided
  7. credit is given to the program's author.
  8.  
  9.     Jerry D. Hedden
  10.     28 Windemere Dr.
  11.     Sicklerville, NJ  08081
  12.     Phone:    (609)629-3975
  13.     Email:    Hedden@ESDSDF.DNet.GE.com
  14.  
  15. ===========================================================================
  16.  
  17. This source code REQUIRES Aztec 'C' v3.6a.  It probably cannot be handled
  18. by any other compiler because of the assumed register usage within the
  19. embedded assembly code.  Make with the following:
  20.  
  21.     as startup
  22.     cc +x3 -e500 -z10000 4d
  23.     ln -m -o "4D Navigator" startup.o 4d.o -lc
  24.  
  25. ===========================================================================
  26.  
  27. The following copyright notice accompanied the source code for Palette
  28. Requester which was used as a model for this program's Color and View
  29. Parameter requesters.
  30.  
  31. Palette Requester -- (c) Copyright 1989 Jonathan Potter
  32. This program is freely redistributable, although all rights to it remain
  33. with the author. It may be used freely in any program as long as this
  34. notice remains intact, however, if you do this, please mention the author
  35. in the program.  If you wish to use this in a commercial program of any
  36. kind, you must register with a $15 donation.
  37. Please send donations, bug reports, comments and suggestions to :
  38.     Jonathan Potter
  39.     3 William Street
  40.     Clarence Park 5034
  41.     South Australia
  42.     Australia
  43.  
  44. ===========================================================================
  45.  
  46. History:
  47.  
  48. v1.00 - 10 Aug 1991
  49.   Initial release
  50.  
  51. **************************************************************************/
  52.  
  53. #include <intuition/intuition.h>
  54.  
  55. #define TIMING 0
  56. #define DEBUG  0
  57.  
  58. /* corrects <exec/memory.h> long integer problems */
  59. #define CLEARED_CHIP    0x00010002L
  60.  
  61. /* determines "grid spacing" */
  62. #define INTERVAL    18 /* degrees */
  63. #define SEGMENTS    (360/INTERVAL)
  64. #define ONE80        (SEGMENTS/2)
  65. #define LATRNG        ((SEGMENTS/4)-1)
  66. #define NUM_GRID_PTS    (long)(SEGMENTS*LATRNG*SEGMENTS)
  67.  
  68. /* circle constants */
  69. #define PI        (float)3.1415926535897932384626433832795
  70. #define HALF_DEG    (float)(PI/360.0)
  71.  
  72. /* rotation constants */
  73. #define RESTART        -1
  74. #define STOPPED     0
  75. #define TEN_DEGREES    20
  76. #define NINETY_DEGREES    180
  77. #define THREE_SIXTY    720
  78.  
  79. /* the 4 coordinates */
  80. #define X 0L
  81. #define Y 1L
  82. #define Z 2L
  83. #define W 3L
  84.  
  85. /* required libraries */
  86. struct Library    *IntuitionBase, *GfxBase, *MathBase, *MathTransBase,
  87.         *_OpenLibrary();
  88.  
  89. /* Motorola FFP math routines */
  90. long  SPFix(), SPCmp(), SPTst();
  91. float SPFlt(), SPNeg(), SPAdd(), SPSub(), SPMul(), SPDiv();
  92. float SPSincos(), SPAcos(), SPSqrt();
  93.  
  94. /* information for display and graphics */
  95. #define WIDTH        656L
  96. #define HEIGHT        430L
  97. #define PLANES        3
  98. #define PLANESIZE    (long)((WIDTH>>3)*HEIGHT)
  99.  
  100. struct Screen *screen, *OpenScreen();
  101. struct ViewPort *vp;
  102. struct Window *window, *OpenWindow();
  103. struct RastPort *rp;
  104. struct IntuiMessage *_GetMsg();
  105. PLANEPTR buffer1[PLANES], buffer2[PLANES];
  106.  
  107. struct NewScreen MyScreen = {
  108.   0,0, WIDTH,HEIGHT,PLANES, 0,1, HIRES|LACE,CUSTOMSCREEN,
  109.   NULL,(UBYTE *)"4D Navigator",NULL,NULL
  110. };
  111.  
  112. struct NewWindow MyWindow = {
  113.   0,0, WIDTH,HEIGHT, 0,1, RAWKEY,
  114.   NOCAREREFRESH|BORDERLESS|ACTIVATE|SIMPLE_REFRESH|RMBTRAP,
  115.   NULL,NULL,NULL,NULL,NULL, WIDTH,HEIGHT, WIDTH,HEIGHT, CUSTOMSCREEN
  116. };
  117.  
  118. /* colors */
  119. #define BLACK    0L
  120. #define WHITE    7L
  121.  
  122. UWORD ColorTables[3][1<<PLANES] = {
  123.   /* B/W    RED   GREEN   R+G    BLUE    R+B    G+B    W/B */
  124.   {0x0000,0x0A00,0x0070,0x0A90,0x000A,0x0B0A,0x0079,0x0CCC},
  125.   {0x0FFF,0x0F00,0x00C0,0x0F90,0x000F,0x0C0E,0x00BA,0x0000},
  126.   /* used by color requester */
  127.   {0x0000,0x0A00,0x0070,0x0A90,0x000A,0x0B0A,0x0079,0x0CCC}
  128. };
  129.  
  130. /* arrays for holding pre-computed, converted "floating point" values */
  131. short *cos, *sin, *factor, *_AllocMem();
  132.  
  133. /* arrays for holding the "GRID" */
  134. short *p4d, *e4d, *x4d, *p3d, *e3d, *x3d, *p2d, *e2d, *x2d;
  135. /* indexing macro for grid points */
  136. #define INDX(i,j,k) (((((i)*LATRNG)+(j))*SEGMENTS)+(k))
  137.  
  138. /* view parameters */
  139. short FrontLimit = 0, BackLimit = 15000, ScaleFactor = 30;
  140.  
  141. /* point is out of range */
  142. #define DONT_PLOT    32000
  143. #asm
  144. NO_PLOT     equ    32000
  145. #endasm
  146.  
  147.  
  148. /* sets up the pre-computed, converted "floating point" arrays */
  149. Initialize()
  150. {
  151.   register long i;
  152.   register float tsin;
  153.   float tcos;
  154.   register float w;
  155.   register short *x, *y;
  156.  
  157.   Countdown();
  158.   x = cos;  y = sin;
  159.   for (i=0; i<720; i++) {
  160.     tsin = SPSincos(&tcos,SPMul(HALF_DEG,SPFlt(i)));
  161.     *(x++) = (SPTst(tcos) >= 0) ? SPFix(SPAdd(0.5,SPMul(tcos,8192.0))) :
  162.                   SPFix(SPSub(0.5,SPMul(tcos,8192.0)));
  163.     *(y++) = (SPTst(tsin) >= 0) ? SPFix(SPAdd(0.5,SPMul(tsin,8192.0))) :
  164.                   SPFix(SPSub(0.5,SPMul(tsin,8192.0)));
  165.   }
  166.  
  167.   Countdown();
  168.   x = factor+1;
  169.   for (i=-8191; i<=8191; i++) {
  170.     if (!(i&0x000001FF))  Countdown();
  171.     w = SPDiv(8192.0,SPFlt(i));
  172.     *(x++) = SPFix(SPAdd(SPMul(SPDiv(SPSqrt(SPSub(SPMul(w,w),1.0)),
  173.                             SPAcos(w)),128.0),0.5));
  174.   }
  175.   Countdown();
  176. }
  177.  
  178.  
  179. /* sets the "GRID" to the "starting position" */
  180. initial_pos()
  181. {
  182.   short plong,lat,elong;
  183.   register short regd4, regd5;
  184.   long ind;
  185.   register long ind1,ind2;
  186.   register short *pts = x4d;
  187.  
  188.   ind = 0;
  189.   for (plong=0; plong<180; plong+=INTERVAL) {
  190.     e4d[ind+X] = p4d[ind+Z] = sin[plong*2];
  191.     e4d[ind+W] = p4d[ind+Y] = cos[plong*2];
  192.     e4d[ind+Y] = e4d[ind+Z] = p4d[ind+X] = p4d[ind+W] = 0;
  193.     e4d[ind+(ONE80*4+X)] = p4d[ind+(ONE80*4+Z)] = sin[(plong+180)*2];
  194.     e4d[ind+(ONE80*4+W)] = p4d[ind+(ONE80*4+Y)] = cos[(plong+180)*2];
  195.     e4d[ind+(ONE80*4+Y)] = e4d[ind+(ONE80*4+Z)] =
  196.     p4d[ind+(ONE80*4+X)] = p4d[ind+(ONE80*4+W)] = 0;
  197.     ind += 4;
  198.     for (lat=INTERVAL; lat<=(90-INTERVAL); lat+=INTERVAL) {
  199.       ind1 = INDX(plong/INTERVAL,(lat/INTERVAL)-1,0)*4;
  200.       ind2 = INDX((plong/INTERVAL)+ONE80,(lat/INTERVAL)-1,ONE80)*4;
  201.       for (elong=0; elong<180; elong+=INTERVAL) {
  202.  
  203.     regd4 = cos[lat*2]; regd5 = sin[plong*2];
  204. #asm
  205.     muls    d4,d5
  206.     moveq    #13,d4
  207.     asr.l    d4,d5
  208. #endasm
  209.     pts[ind1+X] = regd5; regd5 = (-regd5); pts[ind2+X] = regd5;
  210.  
  211.     regd4 = sin[lat*2]; regd5 = cos[elong*2];
  212. #asm
  213.     muls    d4,d5
  214.     moveq    #13,d4
  215.     asr.l    d4,d5
  216. #endasm
  217.     pts[ind1+Y] = regd5; regd5 = (-regd5); pts[ind2+Y] = regd5;
  218.  
  219.     regd4 = sin[lat*2]; regd5 = sin[elong*2];
  220. #asm
  221.     muls    d4,d5
  222.     moveq    #13,d4
  223.     asr.l    d4,d5
  224. #endasm
  225.     pts[ind1+Z] = regd5; regd5 = (-regd5); pts[ind2+Z] = regd5;
  226.  
  227.     regd4 = cos[lat*2]; regd5 = cos[plong*2];
  228. #asm
  229.     muls    d4,d5
  230.     moveq    #13,d4
  231.     asr.l    d4,d5
  232. #endasm
  233.     pts[ind1+W] = regd5; regd5 = (-regd5); pts[ind2+W] = regd5;
  234.  
  235.     ind1+=4; ind2+=4;
  236.       }
  237.       ind1 = INDX(plong/INTERVAL,(lat/INTERVAL)-1,ONE80)*4;
  238.       ind2 = INDX((plong/INTERVAL)+ONE80,(lat/INTERVAL)-1,0)*4;
  239.       for (elong=180; elong<360; elong+=INTERVAL) {
  240.  
  241.     regd4 = cos[lat*2]; regd5 = sin[plong*2];
  242. #asm
  243.     muls    d4,d5
  244.     moveq    #13,d4
  245.     asr.l    d4,d5
  246. #endasm
  247.     pts[ind1+X] = regd5; regd5 = (-regd5); pts[ind2+X] = regd5;
  248.  
  249.     regd4 = sin[lat*2]; regd5 = cos[elong*2];
  250. #asm
  251.     muls    d4,d5
  252.     moveq    #13,d4
  253.     asr.l    d4,d5
  254. #endasm
  255.     pts[ind1+Y] = regd5; regd5 = (-regd5); pts[ind2+Y] = regd5;
  256.  
  257.     regd4 = sin[lat*2]; regd5 = sin[elong*2];
  258. #asm
  259.     muls    d4,d5
  260.     moveq    #13,d4
  261.     asr.l    d4,d5
  262. #endasm
  263.     pts[ind1+Z] = regd5; regd5 = (-regd5); pts[ind2+Z] = regd5;
  264.  
  265.     regd4 = cos[lat*2]; regd5 = cos[plong*2];
  266. #asm
  267.     muls    d4,d5
  268.     moveq    #13,d4
  269.     asr.l    d4,d5
  270. #endasm
  271.     pts[ind1+W] = regd5; regd5 = (-regd5); pts[ind2+W] = regd5;
  272.  
  273.     ind1+=4; ind2+=4;
  274.       }
  275.     }
  276.   }
  277. }
  278.  
  279.  
  280. /* rotates the four-dimensional space */
  281. rotate_4d(dir1,dir2,angle)
  282. long dir1, dir2;
  283. short angle;
  284. {
  285.   short plong,lat,elong;
  286.   register short regd4, regd5, cangle, sangle;
  287.   short *p4d11, *p4d12, *p4d21, *p4d22;
  288.   short *e4d11, *e4d12, *e4d21, *e4d22;
  289.   register short *x4d11, *x4d12;
  290.   short *x4d21, *x4d22;
  291.  
  292.   if (angle == RESTART)  {
  293.     initial_pos();
  294.     return;
  295.   }
  296.  
  297.   cangle = cos[angle];    sangle = sin[angle];
  298.  
  299.   p4d11 = p4d + dir1;
  300.   p4d12 = p4d + dir2;
  301.   p4d21 = p4d + ONE80*4 + dir1;
  302.   p4d22 = p4d + ONE80*4 + dir2;
  303.  
  304.   e4d11 = e4d + dir1;
  305.   e4d12 = e4d + dir2;
  306.   e4d21 = e4d + ONE80*4 + dir1;
  307.   e4d22 = e4d + ONE80*4 + dir2;
  308.  
  309.   x4d11 = x4d + dir1;
  310.   x4d12 = x4d + dir2;
  311.   x4d21 = x4d + INDX(ONE80,0,-ONE80)*4 + dir1;
  312.   x4d22 = x4d + INDX(ONE80,0,-ONE80)*4 + dir2;
  313.  
  314.   for (plong=0; plong++ < ONE80; ) {
  315.     regd4 = *p4d11; regd5 = *p4d12;
  316. #asm
  317.     move.w    d4,d0    ; d1' = d1*cos - d2*sin
  318.     muls    d6,d0
  319.     move.w    d5,d2
  320.     muls    d7,d2
  321.     sub.l    d2,d0
  322.     move.w    d4,d1    ; d2' = d1*sin + d2*cos
  323.     muls    d7,d1
  324.     move.w    d5,d2
  325.     muls    d6,d2
  326.     add.l    d2,d1
  327.     moveq    #13,d3    ; normalize
  328.     asr.l    d3,d0
  329.     asr.l    d3,d1
  330.     move.w    d0,d4
  331.     move.w    d1,d5
  332. #endasm
  333.     *p4d11 = regd4;  regd4 = (-regd4);  *p4d21 = regd4;
  334.     *p4d12 = regd5;  regd5 = (-regd5);  *p4d22 = regd5;
  335.     p4d11+=4; p4d12+=4; p4d21+=4; p4d22+=4;
  336.  
  337.     regd4 = *e4d11; regd5 = *e4d12;
  338. #asm
  339.     move.w    d4,d0
  340.     muls    d6,d0
  341.     move.w    d5,d2
  342.     muls    d7,d2
  343.     sub.l    d2,d0
  344.     move.w    d4,d1
  345.     muls    d7,d1
  346.     move.w    d5,d2
  347.     muls    d6,d2
  348.     add.l    d2,d1
  349.     moveq    #13,d3
  350.     asr.l    d3,d0
  351.     asr.l    d3,d1
  352.     move.w    d0,d4
  353.     move.w    d1,d5
  354. #endasm
  355.     *e4d11 = regd4;  regd4 = (-regd4);  *e4d21 = regd4;
  356.     *e4d12 = regd5;  regd5 = (-regd5);  *e4d22 = regd5;
  357.     e4d11+=4; e4d12+=4; e4d21+=4; e4d22+=4;
  358.  
  359.     for (lat=0; lat++ < LATRNG; ) {
  360.       x4d21 += (SEGMENTS*4);  x4d22 += (SEGMENTS*4);
  361.       for (elong=0; elong++ < ONE80; ) {
  362.     regd4 = *x4d11; regd5 = *x4d12;
  363. #asm
  364.     move.w    d4,d0
  365.     muls    d6,d0
  366.     move.w    d5,d2
  367.     muls    d7,d2
  368.     sub.l    d2,d0
  369.     move.w    d4,d1
  370.     muls    d7,d1
  371.     move.w    d5,d2
  372.     muls    d6,d2
  373.     add.l    d2,d1
  374.     moveq    #13,d3
  375.     asr.l    d3,d0
  376.     asr.l    d3,d1
  377.     move.w    d0,d4
  378.     move.w    d1,d5
  379. #endasm
  380.     *x4d11 = regd4;  regd4 = (-regd4);  *x4d21 = regd4;
  381.     *x4d12 = regd5;  regd5 = (-regd5);  *x4d22 = regd5;
  382.     x4d11+=4; x4d12+=4; x4d21+=4; x4d22+=4;
  383.       }
  384.  
  385.       x4d21 -= (SEGMENTS*4);  x4d22 -= (SEGMENTS*4);
  386.       for (elong=ONE80; elong++ < SEGMENTS; ) {
  387.     regd4 = *x4d11; regd5 = *x4d12;
  388. #asm
  389.     move.w    d4,d0
  390.     muls    d6,d0
  391.     move.w    d5,d2
  392.     muls    d7,d2
  393.     sub.l    d2,d0
  394.     move.w    d4,d1
  395.     muls    d7,d1
  396.     move.w    d5,d2
  397.     muls    d6,d2
  398.     add.l    d2,d1
  399.     moveq    #13,d3
  400.     asr.l    d3,d0
  401.     asr.l    d3,d1
  402.     move.w    d0,d4
  403.     move.w    d1,d5
  404. #endasm
  405.     *x4d11 = regd4;  regd4 = (-regd4);  *x4d21 = regd4;
  406.     *x4d12 = regd5;  regd5 = (-regd5);  *x4d22 = regd5;
  407.     x4d11+=4; x4d12+=4; x4d21+=4; x4d22+=4;
  408.       }
  409.     }
  410.   }
  411. }
  412.  
  413.  
  414. /* maps the four-dimensional space into three dimensions */
  415. map_to_3d()
  416. {
  417.   register short regd4, regd5, regd6, regd7;
  418.   short wval;
  419.   short plong,lat,elong;
  420.   short *p4d1, *p3d1, *p3d2;
  421.   short *e4d1, *e3d1, *e3d2;
  422.   register short *x4d1;
  423.   short *x3d1;
  424.   register short *x3d2;
  425.  
  426.   p4d1 = p4d;  p3d1 = p3d;  p3d2 = p3d + ONE80*3;
  427.   e4d1 = e4d;  e3d1 = e3d;  e3d2 = e3d + ONE80*3;
  428.   x4d1 = x4d;  x3d1 = x3d;  x3d2 = x3d + INDX(ONE80,0,-ONE80)*3;
  429.  
  430.   for (plong=0; plong++ < ONE80; ) {
  431.     if ((wval = *(p4d1+W)) >= 8192) {
  432.       *(p4d1+W) = 8192;
  433.       *(p3d1+X) = *(p4d1+X); *(p3d1+Y) = *(p4d1+Y); *(p3d1+Z) = *(p4d1+Z);
  434.       *(p4d1+ONE80*4+W) = -8192;
  435.       *(p3d2+X) = DONT_PLOT; *(p3d2+Y) = *(p3d2+Z) = 0;
  436.     } else
  437.     if (wval <= -8192) {
  438.       *(p4d1+W) = -8192;
  439.       *(p3d1+X) = DONT_PLOT; *(p3d1+Y) = *(p3d1+Z) = 0;
  440.       *(p4d1+ONE80*4+W) = 8192;
  441.       *(p3d2+X) = (-(*(p4d1+X))); *(p3d2+Y) = (-(*(p4d1+Y)));
  442.       *(p3d2+Z) = (-(*(p4d1+Z)));
  443.     } else {
  444.       regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
  445.  
  446.       regd4 = *(p4d1+X);
  447. #asm
  448. dummy1: move.w    d4,d5
  449.     neg.w    d5
  450.     cmpi.w    #1000,d6
  451.     blt.s    1$
  452.     move.w    #NO_PLOT,d4
  453.     bra.s    2$
  454. 1$    muls    d6,d4
  455.     asr.l    #7,d4
  456.     cmpi.w    #1000,d7
  457.     blt.s    2$
  458.     move.w    #NO_PLOT,d5
  459.     bra.s    3$
  460. 2$    muls    d7,d5
  461.     asr.l    #7,d5
  462. 3$
  463. #endasm
  464.       *(p3d1+X) = regd4; *(p3d2+X) = regd5;
  465.  
  466.       regd4 = *(p4d1+Y);
  467. #asm
  468.     move.w    d4,d5
  469.     neg.w    d5
  470.     muls    d6,d4
  471.     muls    d7,d5
  472.     asr.l    #7,d4
  473.     asr.l    #7,d5
  474. #endasm
  475.       *(p3d1+Y) = regd4; *(p3d2+Y) = regd5;
  476.  
  477.       regd4 = *(p4d1+Z);
  478. #asm
  479.     move.w    d4,d5
  480.     neg.w    d5
  481.     muls    d6,d4
  482.     muls    d7,d5
  483.     asr.l    #7,d4
  484.     asr.l    #7,d5
  485. #endasm
  486.       *(p3d1+Z) = regd4; *(p3d2+Z) = regd5;
  487.     }
  488.     p4d1+=4; p3d1+=3; p3d2+=3;
  489.  
  490.     if ((wval = *(e4d1+W)) >= 8192) {
  491.       *(e4d1+W) = 8192;
  492.       *(e3d1+X) = *(e4d1+X); *(e3d1+Y) = *(e4d1+Y); *(e3d1+Z) = *(e4d1+Z);
  493.       *(e4d1+ONE80*4+W) = -8192;
  494.       *(e3d2+X) = DONT_PLOT; *(e3d2+Y) = *(e3d2+Z) = 0;
  495.     } else
  496.     if (wval <= -8192) {
  497.       *(e4d1+W) = -8192;
  498.       *(e3d1+X) = DONT_PLOT; *(e3d1+Y) = *(e3d1+Z) = 0;
  499.       *(e4d1+ONE80*4+W) = 8192;
  500.       *(e3d2+X) = (-(*(e4d1+X))); *(e3d2+Y) = (-(*(e4d1+Y)));
  501.       *(e3d2+Z) = (-(*(e4d1+Z)));
  502.     } else {
  503.       regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
  504.  
  505.       regd4 = *(e4d1+X);
  506. #asm
  507. dummy2: move.w    d4,d5
  508.     neg.w    d5
  509.     cmpi.w    #1000,d6
  510.     blt.s    1$
  511.     move.w    #NO_PLOT,d4
  512.     bra.s    2$
  513. 1$    muls    d6,d4
  514.     asr.l    #7,d4
  515.     cmpi.w    #1000,d7
  516.     blt.s    2$
  517.     move.w    #NO_PLOT,d5
  518.     bra.s    3$
  519. 2$    muls    d7,d5
  520.     asr.l    #7,d5
  521. 3$
  522. #endasm
  523.       *(e3d1+X) = regd4; *(e3d2+X) = regd5;
  524.  
  525.       regd4 = *(e4d1+Y);
  526. #asm
  527.     move.w    d4,d5
  528.     neg.w    d5
  529.     muls    d6,d4
  530.     muls    d7,d5
  531.     asr.l    #7,d4
  532.     asr.l    #7,d5
  533. #endasm
  534.       *(e3d1+Y) = regd4; *(e3d2+Y) = regd5;
  535.  
  536.       regd4 = *(e4d1+Z);
  537. #asm
  538.     move.w    d4,d5
  539.     neg.w    d5
  540.     muls    d6,d4
  541.     muls    d7,d5
  542.     asr.l    #7,d4
  543.     asr.l    #7,d5
  544. #endasm
  545.       *(e3d1+Z) = regd4; *(e3d2+Z) = regd5;
  546.     }
  547.     e4d1+=4; e3d1+=3; e3d2+=3;
  548.  
  549.     for (lat=0; lat++ < LATRNG; ) {
  550.       x3d2 += (SEGMENTS*3);
  551.       for (elong=0; elong++ < ONE80; ) {
  552.     if ((wval = *(x4d1+W)) >= 8192) {
  553.       *(x4d1+W) = 8192;
  554.       *(x3d1+X) = *(x4d1+X); *(x3d1+Y) = *(x4d1+Y); *(x3d1+Z) = *(x4d1+Z);
  555.       *(x4d1+INDX(ONE80,0,ONE80)*4+W) = -8192;
  556.       *(x3d2+X) = DONT_PLOT; *(x3d2+Y) = *(x3d2+Z) = 0;
  557.     } else
  558.     if (wval <= -8192) {
  559.       *(x4d1+W) = -8192;
  560.       *(x3d1+X) = DONT_PLOT; *(x3d1+Y) = *(x3d1+Z) = 0;
  561.       *(x4d1+INDX(ONE80,0,ONE80)*4+W) = 8192;
  562.       *(x3d2+X) = (-(*(x4d1+X))); *(x3d2+Y) = (-(*(x4d1+Y)));
  563.       *(x3d2+Z) = (-(*(x4d1+Z)));
  564.     } else {
  565.       regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
  566.  
  567.       regd4 = *(x4d1+X);
  568. #asm
  569. dummy3: move.w    d4,d5
  570.     neg.w    d5
  571.     cmpi.w    #1000,d6
  572.     blt.s    1$
  573.     move.w    #NO_PLOT,d4
  574.     bra.s    2$
  575. 1$    muls    d6,d4
  576.     asr.l    #7,d4
  577.     cmpi.w    #1000,d7
  578.     blt.s    2$
  579.     move.w    #NO_PLOT,d5
  580.     bra.s    3$
  581. 2$    muls    d7,d5
  582.     asr.l    #7,d5
  583. 3$
  584. #endasm
  585.       *(x3d1+X) = regd4; *(x3d2+X) = regd5;
  586.  
  587.       regd4 = *(x4d1+Y);
  588. #asm
  589.     move.w    d4,d5
  590.     neg.w    d5
  591.     muls    d6,d4
  592.     muls    d7,d5
  593.     asr.l    #7,d4
  594.     asr.l    #7,d5
  595. #endasm
  596.       *(x3d1+Y) = regd4; *(x3d2+Y) = regd5;
  597.  
  598.       regd4 = *(x4d1+Z);
  599. #asm
  600.     move.w    d4,d5
  601.     neg.w    d5
  602.     muls    d6,d4
  603.     muls    d7,d5
  604.     asr.l    #7,d4
  605.     asr.l    #7,d5
  606. #endasm
  607.       *(x3d1+Z) = regd4; *(x3d2+Z) = regd5;
  608.     }
  609.     x4d1+=4; x3d1+=3; x3d2+=3;
  610.       }
  611.       x3d2 -= (SEGMENTS*3);
  612.       for (elong=ONE80; elong++ < SEGMENTS; ) {
  613.     if ((wval = *(x4d1+W)) >= 8192) {
  614.       *(x4d1+W) = 8192;
  615.       *(x3d1+X) = *(x4d1+X); *(x3d1+Y) = *(x4d1+Y); *(x3d1+Z) = *(x4d1+Z);
  616.       *(x4d1+INDX(ONE80,0,-ONE80)*4+W) = -8192;
  617.       *(x3d2+X) = DONT_PLOT; *(x3d2+Y) = *(x3d2+Z) = 0;
  618.     } else
  619.     if (wval <= -8192) {
  620.       *(x4d1+W) = -8192;
  621.       *(x3d1+X) = DONT_PLOT; *(x3d1+Y) = *(x3d1+Z) = 0;
  622.       *(x4d1+INDX(ONE80,0,-ONE80)*4+W) = 8192;
  623.       *(x3d2+X) = (-(*(x4d1+X))); *(x3d2+Y) = (-(*(x4d1+Y)));
  624.       *(x3d2+Z) = (-(*(x4d1+Z)));
  625.     } else {
  626.       regd6 = factor[8192+wval]; regd7 = factor[8192-wval];
  627.  
  628.       regd4 = *(x4d1+X);
  629. #asm
  630. dummy4: move.w    d4,d5
  631.     neg.w    d5
  632.     cmpi.w    #1000,d6
  633.     blt.s    1$
  634.     move.w    #NO_PLOT,d4
  635.     bra.s    2$
  636. 1$    muls    d6,d4
  637.     asr.l    #7,d4
  638.     cmpi.w    #1000,d7
  639.     blt.s    2$
  640.     move.w    #NO_PLOT,d5
  641.     bra.s    3$
  642. 2$    muls    d7,d5
  643.     asr.l    #7,d5
  644. 3$
  645. #endasm
  646.       *(x3d1+X) = regd4; *(x3d2+X) = regd5;
  647.  
  648.       regd4 = *(x4d1+Y);
  649. #asm
  650.     move.w    d4,d5
  651.     neg.w    d5
  652.     muls    d6,d4
  653.     muls    d7,d5
  654.     asr.l    #7,d4
  655.     asr.l    #7,d5
  656. #endasm
  657.       *(x3d1+Y) = regd4; *(x3d2+Y) = regd5;
  658.  
  659.       regd4 = *(x4d1+Z);
  660. #asm
  661.     move.w    d4,d5
  662.     neg.w    d5
  663.     muls    d6,d4
  664.     muls    d7,d5
  665.     asr.l    #7,d4
  666.     asr.l    #7,d5
  667. #endasm
  668.       *(x3d1+Z) = regd4; *(x3d2+Z) = regd5;
  669.     }
  670.     x4d1+=4; x3d1+=3; x3d2+=3;
  671.       }
  672.     }
  673.   }
  674. }
  675.  
  676.  
  677. /* maps the 3D space into coordinates for the screen */
  678. map_to_screen()
  679. {
  680.   register short scale = (-ScaleFactor), back = BackLimit, front = FrontLimit, temp;
  681.   short plong, lat, elong;
  682.   short *p3d1, *p2d1, *e3d1, *e2d1;
  683.   register short *x3d1, *x2d1;
  684.  
  685.   p3d1 = p3d; p2d1 = p2d;  e3d1 = e3d; e2d1 = e2d;  x3d1 = x3d; x2d1 = x2d;
  686.  
  687.   for (plong=0; plong++ < SEGMENTS; ) {
  688.     if ((temp=*(p3d1+X)) < front  ||  temp > back)
  689.       *(p2d1+X) = DONT_PLOT;
  690.     else {
  691.       *(p2d1+X) = (WIDTH/2) + (*(p3d1+Y)/scale);
  692.       temp = *(p3d1+Z);
  693. #asm
  694.       muls   #7,d7    ; for aspect ratio
  695.       asr.l  #3,d7
  696.       divs   d4,d7    ; *(p2d1+Y) = (HEIGHT/2) + (*(p3d1+Z)/scale);
  697.       add.w  #215,d7
  698. #endasm
  699.       *(p2d1+Y) = temp;
  700.     }
  701.     p3d1+=3;  p2d1+=2;
  702.  
  703.     if ((temp=*(e3d1+X)) < front  ||  temp > back)
  704.       *(e2d1+X) = DONT_PLOT;
  705.     else {
  706.       *(e2d1+X) = (WIDTH/2)  + (*(e3d1+Y)/scale);
  707.       temp = *(e3d1+Z);
  708. #asm
  709.       muls   #7,d7    ; for aspect ratio
  710.       asr.l  #3,d7
  711.       divs   d4,d7    ; *(e2d1+Y) = (HEIGHT/2) + (*(e3d1+Z)/scale);
  712.       add.w  #215,d7
  713. #endasm
  714.       *(e2d1+Y) = temp;
  715.     }
  716.     e3d1+=3;  e2d1+=2;
  717.  
  718.     for (lat=0; lat++ < LATRNG; ) {
  719.       for (elong=0; elong++ < SEGMENTS; ) {
  720.     if ((temp=*(x3d1+X)) < front  ||  temp > back)
  721.       *(x2d1+X) = DONT_PLOT;
  722.     else {
  723.       *(x2d1+X) = (WIDTH/2)  + (*(x3d1+Y)/scale);
  724.       temp = *(x3d1+Z);
  725. #asm
  726.       muls     #7,d7        ; for aspect ratio
  727.       asr.l  #3,d7
  728.       divs     d4,d7        ; *(x2d1+Y) = (HEIGHT/2) + (*(x3d1+Z)/scale);
  729.       add.w  #215,d7
  730. #endasm
  731.       *(x2d1+Y) = temp;
  732.     }
  733.     x3d1+=3;  x2d1+=2;
  734.       }
  735.     }
  736.   }
  737. }
  738.  
  739.  
  740. #define LEFT    1
  741. #define RIGHT    2
  742. #define TOP    4
  743. #define BOTTOM    8
  744.  
  745. /* plots the "GRID" into the screen buffer */
  746. plot_in_buffer()
  747. {
  748.   short i, plong, lat, elong;
  749.   long index;
  750.   register long num;
  751.   short firstx, firsty, farfirst;
  752.   register short x, y;
  753.   short far1;
  754.   register short far2=0;
  755.   register short *toplot, *toget;
  756.   short plot_buf[(SEGMENTS+1)*2];
  757.  
  758.   toplot = plot_buf;
  759.   SetBuffer();
  760.  
  761.   /*** EQUATOR & POLAR RING ***/
  762.   for (i=0; i<2; i++) {
  763.     toget = (i==0) ? e2d: p2d;
  764.     num = 0; far1 = 0;
  765.     if ((firstx = toget[0]) != DONT_PLOT) {
  766.       toplot[0] = firstx;  toplot[1] = firsty = toget[1];  num = 2;
  767.       if (firstx < 0)
  768.     far1 |= LEFT;
  769.       else if (firstx >= WIDTH)
  770.     far1 |= RIGHT;
  771.       if (firsty < 0)
  772.     far1 |= TOP;
  773.       else if (firsty >= HEIGHT)
  774.     far1 |= BOTTOM;
  775.       farfirst = far1;
  776.     }
  777.     for (elong=2; elong<SEGMENTS*2; elong+=2) {
  778.       if ((x = toget[elong]) != DONT_PLOT) {
  779.     y = toget[elong+1];
  780.     if (x < 0)
  781.       far2 |= LEFT;
  782.     else if (x >= WIDTH)
  783.       far2 |= RIGHT;
  784.     if (y < 0)
  785.       far2 |= TOP;
  786.     else if (y >= HEIGHT)
  787.       far2 |= BOTTOM;
  788.     if (far1 & far2) {
  789.       if (num >= 4) {
  790.         Move(rp,(long)toplot[0],(long)toplot[1]);
  791.         PolyDraw(rp,num>>1,toplot);
  792.         num = 2;
  793.       }
  794.       toplot[0] = x;
  795.       toplot[1] = y;
  796.     } else {
  797.       toplot[num++] = x;
  798.       toplot[num++] = y;
  799.     }
  800.     far1 = far2;  far2 = 0;
  801.       } else {
  802.     if (num >= 4) {
  803.       Move(rp,(long)toplot[0],(long)toplot[1]);
  804.       PolyDraw(rp,num>>1,toplot);
  805.     }
  806.     num = 0;  far1 = 0;
  807.       }
  808.     }
  809.     if (num >= 2) {
  810.       if (firstx != DONT_PLOT) {
  811.     if (!(far1 & farfirst)) {
  812.       toplot[num++] = firstx;  toplot[num++] = firsty;
  813.     }
  814.       }
  815.       if (num >= 4) {
  816.     Move(rp,(long)toplot[0],(long)toplot[1]);
  817.     PolyDraw(rp,num>>1,toplot);
  818.       }
  819.     }
  820.   }
  821.  
  822.   toget = x2d;
  823.  
  824.   /*** CIRCUM-EQUATORIAL ***/
  825.   rp->Mask = 0xFC;
  826.   for (lat=0; lat<LATRNG; lat++) {
  827.     for (elong=0; elong<SEGMENTS; elong++) {
  828.       num = 0; far1 = 0;
  829.       index=INDX(0,lat,elong)*2;
  830.       if ((firstx = toget[index]) != DONT_PLOT) {
  831.     toplot[0] = firstx;  toplot[1] = firsty = toget[index+1];  num = 2;
  832.     if (firstx < 0)
  833.       far1 |= LEFT;
  834.     else if (firstx >= WIDTH)
  835.       far1 |= RIGHT;
  836.     if (firsty < 0)
  837.       far1 |= TOP;
  838.     else if (firsty >= HEIGHT)
  839.       far1 |= BOTTOM;
  840.     farfirst = far1;
  841.       }
  842.       for (plong=2; plong<SEGMENTS*2; plong+=2) {
  843.     index += LATRNG*SEGMENTS*2;
  844.     if ((x = toget[index]) != DONT_PLOT) {
  845.       y = toget[index+1];
  846.       if (x < 0)
  847.         far2 |= LEFT;
  848.       else if (x >= WIDTH)
  849.         far2 |= RIGHT;
  850.       if (y < 0)
  851.         far2 |= TOP;
  852.       else if (y >= HEIGHT)
  853.         far2 |= BOTTOM;
  854.       if (far1 & far2) {
  855.         if (num >= 4) {
  856.           Move(rp,(long)toplot[0],(long)toplot[1]);
  857.           PolyDraw(rp,num>>1,toplot);
  858.           num = 2;
  859.         }
  860.         toplot[0] = x;
  861.         toplot[1] = y;
  862.       } else {
  863.         toplot[num++] = x;
  864.         toplot[num++] = y;
  865.       }
  866.       far1 = far2;    far2 = 0;
  867.     } else {
  868.       if (num >= 4) {
  869.         Move(rp,(long)toplot[0],(long)toplot[1]);
  870.         PolyDraw(rp,num>>1,toplot);
  871.       }
  872.       num = 0;  far1 = 0;
  873.     }
  874.       }
  875.       if (num >= 2) {
  876.     if (firstx != DONT_PLOT) {
  877.       if (!(far1 & farfirst)) {
  878.         toplot[num++] = firstx;  toplot[num++] = firsty;
  879.       }
  880.     }
  881.     if (num >= 4) {
  882.       Move(rp,(long)toplot[0],(long)toplot[1]);
  883.       PolyDraw(rp,num>>1,toplot);
  884.     }
  885.       }
  886.     }
  887.   }
  888.  
  889.   /*** CIRCUM-POLAR ***/
  890.   rp->Mask = 0xF9;
  891.   for (lat=0; lat<LATRNG; lat++) {
  892.     for (plong=0; plong<SEGMENTS; plong++) {
  893.       num = 0; far1 = 0;
  894.       index=INDX(plong,lat,0)*2;
  895.       if ((firstx = toget[index]) != DONT_PLOT) {
  896.     toplot[0] = firstx;  toplot[1] = firsty = toget[index+1];  num = 2;
  897.     if (firstx < 0)
  898.       far1 |= LEFT;
  899.     else if (firstx >= WIDTH)
  900.       far1 |= RIGHT;
  901.     if (firsty < 0)
  902.       far1 |= TOP;
  903.     else if (firsty >= HEIGHT)
  904.       far1 |= BOTTOM;
  905.     farfirst = far1;
  906.       }
  907.       for (elong=2; elong<SEGMENTS*2; elong+=2) {
  908.     index += 2;
  909.     if ((x = toget[index]) != DONT_PLOT) {
  910.       y = toget[index+1];
  911.       if (x < 0)
  912.         far2 |= LEFT;
  913.       else if (x >= WIDTH)
  914.         far2 |= RIGHT;
  915.       if (y < 0)
  916.         far2 |= TOP;
  917.       else if (y >= HEIGHT)
  918.         far2 |= BOTTOM;
  919.       if (far1 & far2) {
  920.         if (num >= 4) {
  921.           Move(rp,(long)toplot[0],(long)toplot[1]);
  922.           PolyDraw(rp,num>>1,toplot);
  923.           num = 2;
  924.         }
  925.         toplot[0] = x;
  926.         toplot[1] = y;
  927.       } else {
  928.         toplot[num++] = x;
  929.         toplot[num++] = y;
  930.       }
  931.       far1 = far2;    far2 = 0;
  932.     } else {
  933.       if (num >= 4) {
  934.         Move(rp,(long)toplot[0],(long)toplot[1]);
  935.         PolyDraw(rp,num>>1,toplot);
  936.       }
  937.       num = 0;  far1 = 0;
  938.     }
  939.       }
  940.       if (num >= 2) {
  941.     if (firstx != DONT_PLOT) {
  942.       if (!(far1 & farfirst)) {
  943.         toplot[num++] = firstx;  toplot[num++] = firsty;
  944.       }
  945.     }
  946.     if (num >= 4) {
  947.       Move(rp,(long)toplot[0],(long)toplot[1]);
  948.       PolyDraw(rp,num>>1,toplot);
  949.     }
  950.       }
  951.     }
  952.   }
  953.  
  954.   /*** LONG LINES ***/
  955.   rp->Mask = 0xFA;
  956.   for (elong=0; elong<SEGMENTS; elong++) {
  957.     for (plong=0; plong<SEGMENTS; plong++) {
  958.       num = 0; far1 = 0;
  959.       if (!(elong&1))
  960.     if ((x = e2d[plong*2]) != DONT_PLOT) {
  961.       toplot[0] = x; y = toplot[1] = e2d[plong*2+1];  num=2;
  962.       if (x < 0)
  963.         far1 |= LEFT;
  964.       else if (x >= WIDTH)
  965.         far1 |= RIGHT;
  966.       if (y < 0)
  967.         far1 |= TOP;
  968.       else if (y >= HEIGHT)
  969.         far1 |= BOTTOM;
  970.     }
  971.       index=INDX(plong,0,elong)*2;
  972.       for (lat=0; lat<LATRNG; lat++) {
  973.     if ((x = toget[index]) != DONT_PLOT) {
  974.       y = toget[index+1];
  975.       if (x < 0)
  976.         far2 |= LEFT;
  977.       else if (x >= WIDTH)
  978.         far2 |= RIGHT;
  979.       if (y < 0)
  980.         far2 |= TOP;
  981.       else if (y >= HEIGHT)
  982.         far2 |= BOTTOM;
  983.       if (far1 & far2) {
  984.         if (num >= 4) {
  985.           Move(rp,(long)toplot[0],(long)toplot[1]);
  986.           PolyDraw(rp,num>>1,toplot);
  987.           num = 2;
  988.         }
  989.         toplot[0] = x;
  990.         toplot[1] = y;
  991.       } else {
  992.         toplot[num++] = x;
  993.         toplot[num++] = y;
  994.       }
  995.       far1 = far2;    far2 = 0;
  996.     } else {
  997.       if (num >= 4) {
  998.         Move(rp,(long)toplot[0],(long)toplot[1]);
  999.         PolyDraw(rp,num>>1,toplot);
  1000.       }
  1001.       num = 0;  far1 = 0;
  1002.     }
  1003.     index += SEGMENTS*2;
  1004.       }
  1005.       if (num >= 2) {
  1006.     if (!(plong&1))
  1007.       if ((x = p2d[elong*2]) != DONT_PLOT) {
  1008.         y = p2d[elong*2+1];
  1009.         if (x < 0)
  1010.           far2 |= LEFT;
  1011.         else if (x >= WIDTH)
  1012.           far2 |= RIGHT;
  1013.         if (y < 0)
  1014.           far2 |= TOP;
  1015.         else if (y >= HEIGHT)
  1016.           far2 |= BOTTOM;
  1017.         if (!(far1 & far2)) {
  1018.           toplot[num++] = x; toplot[num++] = y;
  1019.         }
  1020.         far2 = 0;
  1021.       }
  1022.     if (num >= 4) {
  1023.       Move(rp,(long)toplot[0],(long)toplot[1]);
  1024.       PolyDraw(rp,num>>1,toplot);
  1025.     }
  1026.       }
  1027.     }
  1028.   }
  1029.   rp->Mask = 0xFF;
  1030.   DisplayBuffer();
  1031. }
  1032.  
  1033.  
  1034. /* for double buffering */
  1035. SetBuffer()
  1036. {
  1037.   register long i;
  1038.  
  1039.   if (rp->BitMap->Planes[0] == buffer1[0])
  1040.     for (i=0; i<PLANES; i++)
  1041.       rp->BitMap->Planes[i] = buffer2[i];
  1042.   else
  1043.     for (i=0; i<PLANES; i++)
  1044.       rp->BitMap->Planes[i] = buffer1[i];
  1045.   SetRast(rp,BLACK);
  1046. }
  1047.  
  1048.  
  1049. DisplayBuffer()
  1050. {
  1051.   WaitBOVP(vp);
  1052.   WaitTOF();
  1053.   ScrollVPort(vp);
  1054.   RethinkDisplay();
  1055. }
  1056.  
  1057.  
  1058. #define ONE_KEY     1
  1059. #define ZERO_KEY    10
  1060. #define ESCAPE        69
  1061. #define SPACE        64
  1062. #define RKEY        19
  1063. #define TKEY        20
  1064. #define XKEY        50
  1065. #define CKEY        51
  1066. #define VKEY        52
  1067. #define KP8        62
  1068. #define KP2        30
  1069. #define KP4        45
  1070. #define KP6        47
  1071. #define LEFTARROW    79
  1072. #define RIGHTARROW    78
  1073. #define UPARROW     76
  1074. #define DOWNARROW    77
  1075. #define HELP        95
  1076. #if DEBUG
  1077. #define DKEY        34
  1078. #endif
  1079.  
  1080. #define TRANSLATE    1
  1081. #define ROTATE        0
  1082.  
  1083. MainLoop()
  1084. {
  1085.   register struct IntuiMessage *msg;
  1086.   register ULONG class;
  1087.   register USHORT code, qualifier;
  1088.   short mode, amount, step_rate;
  1089.   long fromdir, toward;
  1090.   short ColorSet = BLACK;
  1091. #if TIMING
  1092.   long starttime[3],endtime[3];
  1093. #endif
  1094.  
  1095.   Initialize();
  1096.   mode = TRANSLATE; fromdir = X; toward  = W; amount = RESTART, step_rate = 10;
  1097.  
  1098.   FOREVER {
  1099.     if (amount == STOPPED) {
  1100.       _WaitPort(window->UserPort);
  1101.     } else {
  1102.  
  1103. #if TIMING
  1104.       DateStamp(starttime);
  1105. #endif
  1106.       rotate_4d(fromdir,toward,amount);
  1107.       map_to_3d();
  1108.       map_to_screen();
  1109.       plot_in_buffer();
  1110. #if TIMING
  1111.       DateStamp(endtime);
  1112.       PrintTime("Frame time",starttime,endtime);
  1113. #endif
  1114.       if (amount != step_rate  &&  amount != THREE_SIXTY-step_rate)
  1115.     amount = STOPPED;
  1116.     }
  1117.     while (msg = _GetMsg(window->UserPort)) {
  1118.       class = msg->Class;  code = msg->Code;  qualifier = msg->Qualifier;
  1119.       _ReplyMsg(msg);
  1120.       if (class == RAWKEY) {
  1121.     switch (code) {
  1122. #if DEBUG
  1123.       case DKEY:
  1124.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1125.           dump_coordinates(0);      /* only plotted points */
  1126.         else if (qualifier & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
  1127.           dump_coordinates(1);      /* all points */
  1128.         else
  1129.           dump_screen_plot();
  1130.         break;
  1131. #endif
  1132.       case RKEY:
  1133.       case TKEY:
  1134.          mode = (code == TKEY);
  1135.          break;
  1136.       case XKEY:
  1137.         mode = TRANSLATE;  fromdir = X;  toward  = W;  amount = RESTART;
  1138.         break;
  1139.       case CKEY:
  1140.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) {
  1141.           ColorRequester(ColorSet);
  1142.           if (amount == STOPPED)  plot_in_buffer();
  1143.         } else {
  1144.           ColorSet = 1 - ColorSet;
  1145.           LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  1146.         }
  1147.         break;
  1148.       case VKEY:
  1149.         ViewRequester();
  1150.         if (amount == STOPPED) {
  1151.           map_to_screen();
  1152.           plot_in_buffer();
  1153.         }
  1154.         break;
  1155.       case SPACE:    amount = STOPPED;  break;
  1156.       case KP4:
  1157.       case KP6:
  1158.         fromdir = Y;  toward = (mode) ? W : X;
  1159.         goto calc_amount;
  1160.       case KP8:
  1161.       case KP2:
  1162.         fromdir = Z;  toward = (mode) ? W : X;
  1163.         goto calc_amount;
  1164.       case LEFTARROW:
  1165.       case RIGHTARROW:
  1166.         mode = ROTATE;  fromdir = Z;  toward =  Y;
  1167.         goto calc_amount;
  1168.       case UPARROW:
  1169.       case DOWNARROW:
  1170.         mode = TRANSLATE; fromdir = X; toward =  W;
  1171. calc_amount:
  1172.         if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1173.           amount = TEN_DEGREES;
  1174.         else if (qualifier & IEQUALIFIER_CONTROL)
  1175.           amount = NINETY_DEGREES;
  1176.         else
  1177.           amount = step_rate;
  1178.         if (code == KP2  ||  code == LEFTARROW  ||
  1179.         code == KP6  ||  code == DOWNARROW)
  1180.           amount = THREE_SIXTY - amount;
  1181.         break;
  1182.       case ESCAPE:
  1183.         cleanup(0L);
  1184.       case HELP:
  1185.         LoadRGB4(vp, &ColorTables[0][0], 1L<<PLANES);
  1186.         info();
  1187.         LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  1188.         if (amount == STOPPED)  plot_in_buffer();
  1189.         break;
  1190.       default:
  1191.         if (code >= ONE_KEY  &&  code <= ZERO_KEY) {
  1192.           if (amount != STOPPED)
  1193.         if (amount == step_rate)
  1194.           amount = code;
  1195.         else
  1196.           amount = THREE_SIXTY - code;
  1197.           step_rate = code;
  1198.         }
  1199.     }
  1200.       }
  1201.     }
  1202.   }
  1203. }
  1204.  
  1205.  
  1206. main()
  1207. {
  1208.   long i;
  1209.  
  1210.   if (IntuitionBase = _OpenLibrary("intuition.library", 0L))
  1211.   if (GfxBase       = _OpenLibrary("graphics.library", 0L))
  1212.   if (MathBase      = _OpenLibrary("mathffp.library", 0L))
  1213.   if (MathTransBase = _OpenLibrary("mathtrans.library", 0L))
  1214.   if (p4d = _AllocMem((long)(SEGMENTS*8),0L))
  1215.   if (e4d = _AllocMem((long)(SEGMENTS*8),0L))
  1216.   if (x4d = _AllocMem((long)(NUM_GRID_PTS*8L),0L))
  1217.   if (p3d = _AllocMem((long)(SEGMENTS*6),0L))
  1218.   if (e3d = _AllocMem((long)(SEGMENTS*6),0L))
  1219.   if (x3d = _AllocMem((long)(NUM_GRID_PTS*6L),0L))
  1220.   if (p2d = _AllocMem((long)(SEGMENTS*4),0L))
  1221.   if (e2d = _AllocMem((long)(SEGMENTS*4),0L))
  1222.   if (x2d = _AllocMem((long)(NUM_GRID_PTS*4L),0L))
  1223.   if (cos = _AllocMem(1440L,0L))
  1224.   if (sin = _AllocMem(1440L,0L))
  1225.   if (factor = _AllocMem(32768L,0L))
  1226.   if (screen = OpenScreen(&MyScreen)) {
  1227.     vp = &screen->ViewPort;
  1228.     LoadRGB4(vp,&ColorTables[0][0],1L<<PLANES);
  1229.     MyWindow.Screen = screen;
  1230.   if (window = OpenWindow(&MyWindow)) {
  1231.     rp = window->RPort;
  1232.     SetDrMd(rp,(long)JAM1);
  1233.     SetAPen(rp,WHITE);
  1234.     for (i=0; i<PLANES; i++) {
  1235.       buffer1[i] = rp->BitMap->Planes[i];
  1236.       if (!(buffer2[i] = (PLANEPTR)_AllocMem(PLANESIZE,CLEARED_CHIP)))
  1237.     cleanup(101L);
  1238.     }
  1239.     MainLoop();   /* terminates via cleanup() */
  1240.   }
  1241.   }
  1242.   cleanup(100L);  /* no direct indication of what went wrong above */
  1243. }
  1244.  
  1245.  
  1246. cleanup(code)
  1247. long code;
  1248. {
  1249.   long i;
  1250.  
  1251.   if (p4d)      _FreeMem(p4d,(long)(SEGMENTS*8));
  1252.   if (e4d)      _FreeMem(e4d,(long)(SEGMENTS*8));
  1253.   if (x4d)      _FreeMem(x4d,(long)(NUM_GRID_PTS*8L));
  1254.   if (p3d)      _FreeMem(p3d,(long)((long)SEGMENTS*6L));
  1255.   if (e3d)      _FreeMem(e3d,(long)((long)SEGMENTS*6L));
  1256.   if (x3d)      _FreeMem(x3d,(long)(NUM_GRID_PTS*6L));
  1257.   if (p2d)      _FreeMem(p2d,(long)((long)SEGMENTS*4L));
  1258.   if (e2d)      _FreeMem(e2d,(long)((long)SEGMENTS*4L));
  1259.   if (x2d)      _FreeMem(x2d,(long)(NUM_GRID_PTS*4L));
  1260.   if (cos)      _FreeMem(cos,1440L);
  1261.   if (sin)      _FreeMem(sin,1440L);
  1262.   if (factor)   _FreeMem(factor,32768L);
  1263.   if (window) {
  1264.     if (rp->BitMap->Planes[0] == buffer2[0]) {
  1265.       SetBuffer();
  1266.       DisplayBuffer();
  1267.     }
  1268.     CloseWindow(window);
  1269.   }
  1270.   for (i=0; i<PLANES; i++)
  1271.     if (buffer2[i])     _FreeMem(buffer2[i],PLANESIZE);
  1272.   if (screen)           CloseScreen(screen);
  1273.   if (MathTransBase)    _CloseLibrary(MathTransBase);
  1274.   if (MathBase)         _CloseLibrary(MathBase);
  1275.   if (GfxBase)          _CloseLibrary(GfxBase);
  1276.   if (IntuitionBase)    _CloseLibrary(IntuitionBase);
  1277.   exit(code);
  1278. }
  1279.  
  1280.  
  1281. #define X0    0L
  1282. #define X1    20L
  1283. #define X2    65L
  1284. #define X3    85L
  1285. #define Y0    0L
  1286. #define Y1    20L
  1287. #define Y2    60L
  1288. #define Y3    80L
  1289. #define Y4    120L
  1290. #define Y5    140L
  1291.  
  1292. Digit(n,x,y)
  1293. short n;
  1294. long x,y;
  1295. {
  1296.   /* first a white rectangle */
  1297.   RectFill(rp,x+X0,y+Y0,x+X3,y+Y5);
  1298.   /* then "cut out" the appropriate parts */
  1299.   SetAPen(rp,BLACK);
  1300.   switch (n) {
  1301.     case 0: RectFill(rp,x+X1,y+Y1,x+X2,y+Y4); return;
  1302.     case 1: RectFill(rp,x+X0,y+Y0,x+X2,y+Y5); return;
  1303.     case 2:
  1304.     case 3: RectFill(rp,x+X0,y+Y1,x+X2,y+Y2); break;  /* upper section */
  1305.     case 4: RectFill(rp,x+X1,y+Y0,x+X2,y+Y2);
  1306.         RectFill(rp,x+X0,y+Y3,x+X2,y+Y5); return;
  1307.     case 5:
  1308.     case 6: RectFill(rp,x+X1,y+Y1,x+X3,y+Y2); break;  /* upper section */
  1309.     case 7: RectFill(rp,x+X0,y+Y1,x+X2,y+Y5); return;
  1310.     case 8:
  1311.     case 9: RectFill(rp,x+X1,y+Y1,x+X2,y+Y2);         /* upper section */
  1312.   }
  1313.   /* lower sections */
  1314.   if (n==2)
  1315.     RectFill(rp,x+X1,y+Y3,x+X3,y+Y4);
  1316.   else if (n==3 || n==5 || n==9)
  1317.     RectFill(rp,x+X0,y+Y3,x+X2,y+Y4);
  1318.   else    /* n==6 || n==8 */
  1319.     RectFill(rp,x+X1,y+Y3,x+X2,y+Y4);
  1320. }
  1321.  
  1322.  
  1323. #define TENS_X    225L
  1324. #define ONES_X    340L
  1325. #define DIGITY    115L
  1326.  
  1327. Countdown()
  1328. {
  1329.   static short _counter = 33;
  1330.   SetBuffer();
  1331.   Digit(_counter/10,TENS_X,DIGITY);
  1332.   SetAPen(rp,WHITE);
  1333.   Digit(_counter%10,ONES_X,DIGITY);
  1334.   SetAPen(rp,WHITE);
  1335.   DisplayBuffer();
  1336.   _counter--;
  1337. }
  1338.  
  1339.  
  1340. /*** Info function ***/
  1341.  
  1342. struct TextAttr InfoFont =
  1343.   {(UBYTE *)"topaz.font",8,FS_NORMAL,FPF_ROMFONT|FPF_DESIGNED};
  1344. struct IntuiText Text = {6,0,JAM2,0,0,&InfoFont,NULL,NULL};
  1345.  
  1346. #define TEXT_MARGIN    20L
  1347. #define TEXT_START    25L
  1348.  
  1349. char *InfoTitle  =
  1350.     " 4D Navigator v1.00    \2511991, Jerry D. Hedden, All Rights Reserved";
  1351. char *InfoText[] = {
  1352. "You are embedded within the three-dimensional 'surface' of a four-dimensional",
  1353. "sphere.  Your initial position is on the equator looking east.  The 'north",
  1354. "pole' of the polar ring is to your left.  Pressing 'x' will reset you back to",
  1355. "this initial position.  To quit, press 'esc'.",
  1356. "",
  1357. "You can move (translate) or turn (rotate) using the arrow- and keypad keys.",
  1358. "The up/down arrows send you moving forward/backward; the left/right arrows",
  1359. "rotate you clockwise/counterclockwise.  The keypad 8, 2, 4 and 6 represent",
  1360. "the up, down, left and right directions.  Pressing 't' sets translate mode",
  1361. "such that the keypad moves you in the appropriated directions; 'r' set rotate",
  1362. "mode so you can turn.  Pressing an arrow-/keypad key alone causes its action",
  1363. "to repeat continuously.  Press 'space' to stop.  The change between frames",
  1364. "can be set from 0.5\260 to 5\260 using the keyboard 1 thru 0.  'Shift-' arrow-/",
  1365. "keypad keys cause a single 10\260 change; 'ctrl-' causes a 90\260 change.",
  1366. "",
  1367. "The view of your three-dimensional space is controlled by three parameters --",
  1368. "the scaling factor, the front cutoff, and the rear cutoff.  The first con-",
  1369. "trols the width/height of your view; the other two control its depth.  Press",
  1370. "'v' to bring up a requester to change these values.  N.B.  Your view of the",
  1371. "space is mapped to the screen without perspective.",
  1372. "",
  1373. "The coordinate system is:  Latitude (LAT) -- the angular distance between the",
  1374. "equator (0\260) and the polar ring (90\260); Polar Longitude (PLONG) -- the angular",
  1375. "direction around the polar ring (0\260 - 360\260); and Equatorial Longitude (ELONG)",
  1376. "-- the angular direction around the equator (0\260 - 360\260).  This is an extrap-",
  1377. "olation into three dimensions of latitude and longitude as used on the earth.",
  1378. "",
  1379. "The two white 'circles' are the equator and the polar ring.  Green 'longi-",
  1380. "tude' lines run between them -- connecting points with the same PLONG and",
  1381. "ELONG.  Red connects points with the same LAT and PLONG, and blue connects",
  1382. "points with the same LAT and ELONG.",
  1383. "",
  1384. "Press 'c' to toggle between two color sets (the 'white' set is intended for",
  1385. "printing).  'Shift-c' brings up a color requester.",
  1386. "",
  1387. "The 4D Navigator source code is a combination of 'C' and assembly using Manx",
  1388. "Aztec 'C' v3.6a.  The source contains examples of double-buffering, fixed-",
  1389. "and floating-point math, and in-line assembly code.  I also used some of the",
  1390. "code from Jonathan Potter's color requester.  Send $5.00 to obtain a disk",
  1391. "containing source code and updated program.",
  1392. "",
  1393. "        Comments, questions, bug reports, source requests:",
  1394. "",
  1395. "                       Jerry D. Hedden",
  1396. "                       28 Windemere Dr.",
  1397. "                       Sicklerville, NJ  08081",
  1398. "                       Phone:  (609)629-3975",
  1399. "                       Email:  Hedden@ESDSDF.DNet.GE.com",
  1400. NULL
  1401. };
  1402.  
  1403.  
  1404. info()
  1405. {
  1406.   register long line;
  1407.   register struct Window *info_window;
  1408.   register struct IntuiMessage *msg;
  1409.   register ULONG class;
  1410.   register short all_done;
  1411.  
  1412.   MyWindow.IDCMPFlags = CLOSEWINDOW;
  1413.   MyWindow.Flags = SIMPLE_REFRESH|NOCAREREFRESH|ACTIVATE|WINDOWCLOSE;
  1414.   MyWindow.Title = (UBYTE *)InfoTitle;
  1415.  
  1416.   if (!(info_window = OpenWindow(&MyWindow)))   return;
  1417.  
  1418.   for (line = 0; Text.IText = (UBYTE *)InfoText[line]; line++)
  1419.     PrintIText(info_window->RPort,&Text,TEXT_MARGIN,TEXT_START+(line<<3));
  1420.  
  1421.   for (all_done=0; !all_done; ) {
  1422.     _WaitPort(info_window->UserPort);
  1423.     while (msg = _GetMsg(info_window->UserPort)) {
  1424.       class = msg->Class;
  1425.       _ReplyMsg(msg);
  1426.       if (class == CLOSEWINDOW)  all_done = 1;
  1427.     }
  1428.   }
  1429.   CloseWindow(info_window);
  1430. }
  1431.  
  1432.  
  1433. /*** common requester stuff ***/
  1434.  
  1435. #define RESET    41
  1436. #define CANCEL    42
  1437. #define OKAY    43
  1438.  
  1439. short border_xy[] = {0,0, 115,0, 115,10, 0,10, 0,0};
  1440. struct Border MyBorder = {-1,-1,4,0,JAM1,5,border_xy,NULL};
  1441.  
  1442. struct IntuiText
  1443.   OkayText   = {2,0,JAM1, 41,1,NULL,(UBYTE *)"OKAY",  NULL},
  1444.   ResetText  = {3,0,JAM1, 37,1,NULL,(UBYTE *)"RESET", NULL},
  1445.   CancelText = {1,0,JAM1, 33,1,NULL,(UBYTE *)"CANCEL",NULL};
  1446.  
  1447. struct Image PropImage1, PropImage2, PropImage3;
  1448.  
  1449. struct Window *ReqWindow;
  1450.  
  1451.  
  1452. /*** Color Requester ***/
  1453.  
  1454.  
  1455. #define RED    31
  1456. #define GREEN    32
  1457. #define BLUE    33
  1458.  
  1459. struct IntuiText
  1460.   RedText    = {1,0,JAM1,-14,2,NULL,(UBYTE *)"R",NULL},
  1461.   GreenText  = {2,0,JAM1,-14,2,NULL,(UBYTE *)"G",NULL},
  1462.   BlueText   = {4,0,JAM1,-14,2,NULL,(UBYTE *)"B",NULL},
  1463.   ValuesText = {0,1,JAM2,  0,0,NULL,(UBYTE *)"RGB",NULL};
  1464.  
  1465. struct PropInfo
  1466.   RedProp   = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
  1467.   GreenProp = {AUTOKNOB|FREEHORIZ,0,0,0x1000},
  1468.   BlueProp  = {AUTOKNOB|FREEHORIZ,0,0,0x1000};
  1469.  
  1470. struct Image CurColorImage = {0,0,235,8,1,NULL,0,1,NULL};
  1471.  
  1472. struct Gadget
  1473.   RedCGadg = {NULL,24,54,100,11,
  1474.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  1475.     (APTR)&PropImage1,NULL,&RedText,NULL,(APTR)&RedProp,RED,NULL},
  1476.   GreenCGadg = {&RedCGadg,24,66,100,11,
  1477.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  1478.     (APTR)&PropImage2,NULL,&GreenText,NULL,(APTR)&GreenProp,GREEN,NULL},
  1479.   BlueCGadg = {&GreenCGadg,24,78,100,11,
  1480.     GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET,
  1481.     (APTR)&PropImage3,NULL,&BlueText,NULL,(APTR)&BlueProp,BLUE,NULL},
  1482.   OkayCGadg = {&BlueCGadg,130,79,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  1483.     (APTR)&MyBorder,NULL,&OkayText,NULL,NULL,OKAY,NULL},
  1484.   ResetCGadg = {&OkayCGadg,130,67,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  1485.     (APTR)&MyBorder,NULL,&ResetText,NULL,NULL,RESET,NULL},
  1486.   CancelCGadg = {&ResetCGadg,130,55,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET,
  1487.     (APTR)&MyBorder,NULL,&CancelText,NULL,NULL,CANCEL,NULL};
  1488.  
  1489. struct NewWindow ColorNewWindow={
  1490.   40,23,255,93,1,4,GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY,
  1491.   ACTIVATE|SIMPLE_REFRESH|NOCAREREFRESH|RMBTRAP,
  1492.   &CancelCGadg,NULL,(UBYTE *)" 4D Navigator Color Requester",
  1493.   NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  1494.  
  1495. long CurColor;
  1496.  
  1497.  
  1498. ColorRequester(ColorSet)
  1499. short ColorSet;
  1500. {
  1501.   register long i;
  1502.   register ULONG Class;
  1503.   register USHORT Code, GadgetID;
  1504.   register struct IntuiMessage *msg;
  1505.  
  1506.   ColorNewWindow.Screen = screen;
  1507.   if (!(ReqWindow = OpenWindow(&ColorNewWindow)))  return;
  1508.  
  1509.   for (i=0; i < (1<<PLANES); i++)
  1510.     ColorTables[2][i] = ColorTables[ColorSet][i];
  1511.  
  1512.   DrawPalette(PLANES);
  1513.   CurColorImage.PlaneOnOff = CurColor = 1;
  1514.   ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
  1515.   ValuesText.BackPen = 1;
  1516.   DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
  1517.   SetRGBProps();
  1518.  
  1519.   FOREVER {
  1520.     _WaitPort(ReqWindow->UserPort);
  1521.     while (msg = _GetMsg(ReqWindow->UserPort)) {
  1522.       Class = msg->Class;  Code = msg->Code;
  1523.       if (Class == GADGETUP  ||  Class == GADGETDOWN)
  1524.     GadgetID = ((struct Gadget *)msg->IAddress)->GadgetID;
  1525.       _ReplyMsg(msg);
  1526.       switch (Class) {
  1527.     case MOUSEBUTTONS: {
  1528.       long x,y;
  1529.       long NewColor, ReadPixel();
  1530.       if (Code != SELECTDOWN)  break;
  1531.       x=ReqWindow->MouseX;    y=ReqWindow->MouseY;
  1532.       if (x<12 || x>243 || y<15 || y>40)  break;
  1533.       if (CurColor == (NewColor = ReadPixel(ReqWindow->RPort,x,y)))  break;
  1534.       CurColorImage.PlaneOnOff = CurColor = NewColor;
  1535.       DrawImage(ReqWindow->RPort,&CurColorImage,10L,45L);
  1536.       SetRGBProps();
  1537.       break;
  1538.       }
  1539.     case GADGETDOWN:
  1540.       if (GadgetID >= RED  &&  GadgetID <= BLUE) {
  1541.         do {
  1542.           ReadRGBProps();
  1543.         } while (!(msg = _GetMsg(ReqWindow->UserPort)));
  1544.         _ReplyMsg(msg);
  1545.         ReadRGBProps();
  1546.       }
  1547.       break;
  1548.     case RAWKEY:
  1549.       if (Code != ESCAPE)  break;
  1550.       GadgetID = RESET;
  1551.     case GADGETUP:
  1552.       switch (GadgetID) {
  1553.         case RESET:
  1554.           for (i=0; i < (1<<PLANES); i++)
  1555.         ColorTables[2][i] = ColorTables[ColorSet][i];
  1556.           LoadRGB4(vp, &ColorTables[2][0], 1L<<PLANES);
  1557.           SetRGBProps();
  1558.           break;
  1559.         case OKAY:
  1560.           for (i=0; i < (1<<PLANES); i++)
  1561.         ColorTables[ColorSet][i] = ColorTables[2][i];
  1562.         case CANCEL:
  1563.           LoadRGB4(vp, &ColorTables[ColorSet][0], 1L<<PLANES);
  1564.           while (msg = _GetMsg(ReqWindow->UserPort))  _ReplyMsg(msg);
  1565.           CloseWindow(ReqWindow);
  1566.           return;
  1567.       }
  1568.       }
  1569.     }
  1570.   }
  1571. }
  1572.  
  1573.  
  1574. SetRGBProps()
  1575. {
  1576.   register UWORD cval = ColorTables[2][CurColor];
  1577.   NewModifyProp(&RedCGadg,  ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1578.             (long)(((cval>>8)&0xf)*0x1111),0L,0x1000L,0L,1L);
  1579.   NewModifyProp(&GreenCGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1580.             (long)(((cval>>4)&0xf)*0x1111),0L,0x1000L,0L,1L);
  1581.   NewModifyProp(&BlueCGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1582.             (long)((cval&0xf)*0x1111),0L,0x1000L,0L,1L);
  1583.   ShowRGBValues();
  1584. }
  1585.  
  1586.  
  1587. ReadRGBProps()
  1588. {
  1589.   register long re,gr,bl;
  1590.  
  1591.   re = RedProp.  HorizPot >> 12;
  1592.   gr = GreenProp.HorizPot >> 12;
  1593.   bl = BlueProp. HorizPot >> 12;
  1594.   ColorTables[2][CurColor] = (re<<8)|(gr<<4)|bl;
  1595.   SetRGB4(vp,CurColor,re,gr,bl);
  1596.   ShowRGBValues();
  1597. }
  1598.  
  1599.  
  1600. char *hex = "0123456789ABCDEF";
  1601.  
  1602. ShowRGBValues()
  1603. {
  1604.   register UWORD cval = ColorTables[2][CurColor];
  1605.   ValuesText.IText[0] = hex[(cval>>8)&0xf];
  1606.   ValuesText.IText[1] = hex[(cval>>4)&0xf];
  1607.   ValuesText.IText[2] = hex[ cval    &0xf];
  1608.   ValuesText.FrontPen = CurColor^((1<<PLANES)-1);
  1609.   ValuesText.BackPen  = CurColor;
  1610.   PrintIText(ReqWindow->RPort,&ValuesText,115L,45L);
  1611. }
  1612.  
  1613.  
  1614. DrawPalette(depth)
  1615. int depth;
  1616. {
  1617.   long w,h,ox,x,y,i;
  1618.  
  1619. #if PLANES>3
  1620.   if (depth==4)
  1621.     { w=29; h=12; ox=13; }
  1622.   else if (depth==5)
  1623.     { w=14; h=12; ox=17; }
  1624.   else
  1625. #endif
  1626.     { w=235/(1<<depth); h=25; ox=12; }
  1627.   i=0; x=ox; y=15;
  1628.   for (i=0; i<(1<<depth); i++) {
  1629.     SetAPen(ReqWindow->RPort,i);
  1630.     RectFill(ReqWindow->RPort,x,y,x+w,y+h);
  1631. #if PLANES>3
  1632.     if (depth>3 && i==(1<<(depth-1))-1) {
  1633.       x=ox; y+=h;
  1634.     } else
  1635. #endif
  1636.       x+=w;
  1637.   }
  1638. }
  1639.  
  1640.  
  1641. /*** View Requester ***/
  1642.  
  1643. #define FRONT    31
  1644. #define BACK    32
  1645. #define SCALE    33
  1646.  
  1647. #define TEXTX    5L
  1648. #define TEXTY    -10L
  1649. #define GADGX    8L
  1650. #define FGADY    25L
  1651. #define BGADY    50L
  1652. #define SGADY    75L
  1653. #define FBODY    126L
  1654. #define BBODY    126L
  1655. #define SBODY    661L
  1656.  
  1657. struct IntuiText
  1658.   FrontText = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Front Cutoff:       ",NULL},
  1659.   BackText  = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Rear Cutoff :       ",NULL},
  1660.   ScaleText = {6,0,JAM2,TEXTX,TEXTY,NULL,(UBYTE *)"Scaling Factor:     ",NULL};
  1661.  
  1662. struct PropInfo
  1663.   FrontProp = {AUTOKNOB|FREEHORIZ,0,0,FBODY},
  1664.   BackProp  = {AUTOKNOB|FREEHORIZ,0,0,BBODY},
  1665.   ScaleProp = {AUTOKNOB|FREEHORIZ,0,0,SBODY};
  1666.  
  1667. struct Gadget
  1668.   FrontVGadg = {NULL, GADGX,FGADY, 640,11,
  1669.     GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
  1670.     (APTR)&PropImage1, NULL, &FrontText, NULL, (APTR)&FrontProp, FRONT, NULL},
  1671.   BackVGadg  = {&FrontVGadg, GADGX,BGADY, 640,11,
  1672.     GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
  1673.     (APTR)&PropImage2, NULL, &BackText, NULL, (APTR)&BackProp, BACK, NULL},
  1674.   ScaleVGadg = {&BackVGadg, GADGX,SGADY, 265,11,
  1675.     GADGHNONE|GADGIMAGE, RELVERIFY|GADGIMMEDIATE, PROPGADGET,
  1676.     (APTR)&PropImage3, NULL, &ScaleText, NULL, (APTR)&ScaleProp, SCALE, NULL},
  1677.   OkayVGadg   = {&ScaleVGadg, 285,SGADY+1, 114,9,
  1678.     GADGHCOMP, RELVERIFY, BOOLGADGET,
  1679.     (APTR)&MyBorder, NULL, &OkayText, NULL, NULL, OKAY, NULL},
  1680.   ResetVGadg  = {&OkayVGadg,    409,SGADY+1, 114,9,
  1681.     GADGHCOMP, RELVERIFY, BOOLGADGET,
  1682.     (APTR)&MyBorder, NULL, &ResetText, NULL, NULL, RESET, NULL},
  1683.   CancelVGadg = {&ResetVGadg, 533,SGADY+1, 114,9,
  1684.     GADGHCOMP, RELVERIFY, BOOLGADGET,
  1685.     (APTR)&MyBorder, NULL, &CancelText, NULL, NULL, CANCEL, NULL};
  1686.  
  1687. struct NewWindow ViewNewWindow={
  1688.   0,50, 656,93, 1,4, GADGETUP|GADGETDOWN|MOUSEBUTTONS,
  1689.   ACTIVATE|SIMPLE_REFRESH|NOCAREREFRESH|RMBTRAP,
  1690.   &CancelVGadg,NULL,(UBYTE *)"  4D Navigator View Modifiers",
  1691.   NULL,NULL,0,0,0,0,CUSTOMSCREEN};
  1692.  
  1693. short NewFront, NewBack, NewScale;
  1694.  
  1695.  
  1696. ViewRequester()
  1697. {
  1698.   register ULONG Class;
  1699.   register USHORT GadgetID;
  1700.   register struct IntuiMessage *msg;
  1701.  
  1702.   ViewNewWindow.Screen = screen;
  1703.   if (!(ReqWindow = OpenWindow(&ViewNewWindow)))  return;
  1704.  
  1705.   SetViewProps();
  1706.  
  1707.   FOREVER {
  1708.     _WaitPort(ReqWindow->UserPort);
  1709.     while (msg = _GetMsg(ReqWindow->UserPort)) {
  1710.       Class = msg->Class;
  1711.       if (Class == GADGETUP  ||  Class == GADGETDOWN)
  1712.     GadgetID = ((struct Gadget *)msg->IAddress)->GadgetID;
  1713.       _ReplyMsg(msg);
  1714.       switch (Class) {
  1715.     case GADGETDOWN:
  1716.       if (GadgetID >= FRONT  &&  GadgetID <= SCALE) {
  1717.         do {
  1718.           ReadViewProps();
  1719.         } while (!(msg = _GetMsg(ReqWindow->UserPort)));
  1720.         _ReplyMsg(msg);
  1721.         ReadViewProps();
  1722.       }
  1723.       break;
  1724.     case GADGETUP:
  1725.       switch (GadgetID) {
  1726.         case RESET:
  1727.           SetViewProps();
  1728.           break;
  1729.         case OKAY:
  1730.           if (NewFront == NewBack)
  1731.         if (NewFront > 0)
  1732.           NewFront -= 100;
  1733.         else
  1734.           NewBack += 100;
  1735.           if (NewFront < NewBack) {
  1736.         FrontLimit = NewFront;
  1737.         BackLimit = NewBack;
  1738.           } else {
  1739.         FrontLimit = NewBack;
  1740.         BackLimit = NewFront;
  1741.           }
  1742.           ScaleFactor = NewScale;
  1743.         case CANCEL:
  1744.           while (msg=_GetMsg(ReqWindow->UserPort))  _ReplyMsg(msg);
  1745.           CloseWindow(ReqWindow);
  1746.           return;
  1747.       }
  1748.       }
  1749.     }
  1750.   }
  1751. }
  1752.  
  1753.  
  1754. SetViewProps()
  1755. {
  1756.   NewFront = FrontLimit;
  1757.   NewBack  = BackLimit;
  1758.   NewScale = ScaleFactor;
  1759.   NewModifyProp(&FrontVGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1760.             (ULONG)(((NewFront/100)+258)*127),0L,FBODY,0L,1L);
  1761.   NewModifyProp(&BackVGadg, ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1762.             (ULONG)(((NewBack /100)+258)*127),0L,BBODY,0L,1L);
  1763.   NewModifyProp(&ScaleVGadg,ReqWindow,0L,(long)(FREEHORIZ|AUTOKNOB),
  1764.                 (ULONG)((NewScale-1)*661),0L,SBODY,0L,1L);
  1765.   ShowViewValues();
  1766. }
  1767.  
  1768.  
  1769. ReadViewProps()
  1770. {
  1771.   NewFront = (((USHORT)FrontProp.HorizPot/127)-258)*100;
  1772.   NewBack  = (((USHORT)BackProp .HorizPot/127)-258)*100;
  1773.   NewScale = ( (USHORT)ScaleProp.HorizPot/656)+1;
  1774.   ShowViewValues();
  1775. }
  1776.  
  1777.  
  1778. ShowViewValues()
  1779. {
  1780.   SPrintF(&FrontText.IText[14],"%6d",NewFront);
  1781.   SPrintF(&BackText. IText[14],"%6d",NewBack);
  1782.   SPrintF(&ScaleText.IText[17],"%3d",NewScale);
  1783.   PrintIText(ReqWindow->RPort,&FrontText,GADGX,FGADY);
  1784.   PrintIText(ReqWindow->RPort,&BackText, GADGX,BGADY);
  1785.   PrintIText(ReqWindow->RPort,&ScaleText,GADGX,SGADY);
  1786. }
  1787.  
  1788.  
  1789. #asm
  1790.  
  1791. ; A small sprintf() function using the Exec library RawDoFmt() function
  1792.  
  1793.     public    _SysBase,_LVORawDoFmt
  1794.  
  1795.     public    _SPrintF
  1796. _SPrintF
  1797.     movem.l a2/a3,-(sp)
  1798.     move.l    16(sp),a0
  1799.     lea.l    20(sp),a1
  1800.     lea.l    put_ch(pc),a2
  1801.     move.l    12(sp),a3
  1802.     move.l    _SysBase,a6
  1803.     jsr    _LVORawDoFmt(a6)
  1804.     movem.l (sp)+,a2/a3
  1805.     rts
  1806.  
  1807. put_ch    move.b    d0,(a3)+
  1808.     rts
  1809.  
  1810.  
  1811. ; Stubs for accessing the math libraries
  1812.  
  1813.     public    _MathBase
  1814.     public    _MathTransBase
  1815.  
  1816. _LVOSPCeil    equ    -96
  1817. _LVOSPFloor    equ    -90
  1818. _LVOSPDiv    equ    -84
  1819. _LVOSPMul    equ    -78
  1820. _LVOSPSub    equ    -72
  1821. _LVOSPAdd    equ    -66
  1822. _LVOSPNeg    equ    -60
  1823. _LVOSPAbs    equ    -54
  1824. _LVOSPTst    equ    -48
  1825. _LVOSPCmp    equ    -42
  1826. _LVOSPFlt    equ    -36
  1827. _LVOSPFix    equ    -30
  1828.  
  1829. _LVOSPLog10    equ    -126
  1830. _LVOSPAcos    equ    -120
  1831. _LVOSPAsin    equ    -114
  1832. _LVOSPFieee    equ    -108
  1833. _LVOSPTieee    equ    -102
  1834. _LVOSPSqrt    equ    -96
  1835. _LVOSPPow    equ    -90
  1836. _LVOSPLog    equ    -84
  1837. _LVOSPExp    equ    -78
  1838. _LVOSPTanh    equ    -72
  1839. _LVOSPCosh    equ    -66
  1840. _LVOSPSinh    equ    -60
  1841. _LVOSPSincos    equ    -54
  1842. _LVOSPTan    equ    -48
  1843. _LVOSPCos    equ    -42
  1844. _LVOSPSin    equ    -36
  1845. _LVOSPAtan    equ    -30
  1846.  
  1847.  
  1848.     public    _SPFix
  1849. _SPFix
  1850.     move.l    4(sp),d0
  1851.     move.l    _MathBase,a6
  1852.     jmp    _LVOSPFix(a6)
  1853.  
  1854.     public    _SPFlt
  1855. _SPFlt
  1856.     move.l    4(sp),d0
  1857.     move.l    _MathBase,a6
  1858.     jmp    _LVOSPFlt(a6)
  1859.  
  1860.     public    _SPCmp
  1861. _SPCmp
  1862.     move.l    4(sp),d1
  1863.     move.l    12(sp),d0
  1864.     move.l    _MathBase,a6
  1865.     jmp    _LVOSPCmp(a6)
  1866.  
  1867.     public    _SPNeg
  1868. _SPNeg
  1869.     move.l    4(sp),d0
  1870.     move.l    _MathBase,a6
  1871.     jmp    _LVOSPNeg(a6)
  1872.  
  1873.     public    _SPAdd
  1874. _SPAdd
  1875.     move.l    4(sp),d1
  1876.     move.l    12(sp),d0
  1877.     move.l    _MathBase,a6
  1878.     jmp    _LVOSPAdd(a6)
  1879.  
  1880.     public    _SPSub
  1881. _SPSub
  1882.     move.l    4(sp),d1
  1883.     move.l    12(sp),d0
  1884.     move.l    _MathBase,a6
  1885.     jmp    _LVOSPSub(a6)
  1886.  
  1887.     public    _SPMul
  1888. _SPMul
  1889.     move.l    4(sp),d1
  1890.     move.l    12(sp),d0
  1891.     move.l    _MathBase,a6
  1892.     jmp    _LVOSPMul(a6)
  1893.  
  1894.     public    _SPDiv
  1895. _SPDiv
  1896.     move.l    4(sp),d1
  1897.     move.l    12(sp),d0
  1898.     move.l    _MathBase,a6
  1899.     jmp    _LVOSPDiv(a6)
  1900.  
  1901.     public    _SPTst
  1902. _SPTst
  1903.     move.l    4(sp),d1
  1904.     move.l    _MathBase,a6
  1905.     jmp    _LVOSPTst(a6)
  1906.  
  1907. ;     public  _SPAbs
  1908. ;_SPAbs
  1909. ;     move.l  4(sp),d0
  1910. ;     move.l  _MathBase,a6
  1911. ;     jmp     _LVOSPAbs(a6)
  1912. ;
  1913. ;     public  _SPCeil
  1914. ;_SPCeil
  1915. ;     move.l  4(sp),d0
  1916. ;     move.l  _MathBase,a6
  1917. ;     jmp     _LVOSPCeil(a6)
  1918. ;
  1919. ;     public  _SPFloor
  1920. ;_SPFloor
  1921. ;     move.l  4(sp),d0
  1922. ;     move.l  _MathBase,a6
  1923. ;     jmp     _LVOSPFloor(a6)
  1924.  
  1925.  
  1926.     public    _SPSqrt
  1927. _SPSqrt
  1928.     move.l    4(sp),d0
  1929.     move.l    _MathTransBase,a6
  1930.     jmp    _LVOSPSqrt(a6)
  1931.  
  1932.     public    _SPSincos
  1933. _SPSincos
  1934.     move.l    4(sp),d1
  1935.     move.l    8(sp),d0
  1936.     move.l    _MathTransBase,a6
  1937.     jmp    _LVOSPSincos(a6)
  1938.  
  1939. ;     public  _SPSin
  1940. ;_SPSin
  1941. ;     move.l  4(sp),d0
  1942. ;     move.l  _MathTransBase,a6
  1943. ;     jmp     _LVOSPSin(a6)
  1944. ;
  1945. ;     public  _SPCos
  1946. ;_SPCos
  1947. ;     move.l  4(sp),d0
  1948. ;     move.l  _MathTransBase,a6
  1949. ;     jmp     _LVOSPCos(a6)
  1950. ;
  1951. ;     public  _SPTan
  1952. ;_SPTan
  1953. ;     move.l  4(sp),d0
  1954. ;     move.l  _MathTransBase,a6
  1955. ;     jmp     _LVOSPTan(a6)
  1956. ;
  1957. ;     public  _SPAsin
  1958. ;_SPAsin
  1959. ;     move.l  4(sp),d0
  1960. ;     move.l  _MathTransBase,a6
  1961. ;     jmp     _LVOSPAsin(a6)
  1962.  
  1963.     public    _SPAcos
  1964. _SPAcos
  1965.     move.l    4(sp),d0
  1966.     move.l    _MathTransBase,a6
  1967.     jmp    _LVOSPAcos(a6)
  1968.  
  1969. ;     public  _SPAtan
  1970. ;_SPAtan
  1971. ;     move.l  4(sp),d0
  1972. ;     move.l  _MathTransBase,a6
  1973. ;     jmp     _LVOSPAtan(a6)
  1974. ;
  1975. ;     public  _SPSinh
  1976. ;_SPSinh
  1977. ;     move.l  4(sp),d0
  1978. ;     move.l  _MathTransBase,a6
  1979. ;     jmp     _LVOSPSinh(a6)
  1980. ;
  1981. ;     public  _SPCosh
  1982. ;_SPCosh
  1983. ;     move.l  4(sp),d0
  1984. ;     move.l  _MathTransBase,a6
  1985. ;     jmp     _LVOSPCosh(a6)
  1986. ;
  1987. ;     public  _SPTanh
  1988. ;_SPTanh
  1989. ;     move.l  4(sp),d0
  1990. ;     move.l  _MathTransBase,a6
  1991. ;     jmp     _LVOSPTanh(a6)
  1992. ;
  1993. ;     public  _SPExp
  1994. ;_SPExp
  1995. ;     move.l  4(sp),d0
  1996. ;     move.l  _MathTransBase,a6
  1997. ;     jmp     _LVOSPExp(a6)
  1998. ;
  1999. ;     public  _SPLog
  2000. ;_SPLog
  2001. ;     move.l  4(sp),d0
  2002. ;     move.l  _MathTransBase,a6
  2003. ;     jmp     _LVOSPLog(a6)
  2004. ;
  2005. ;     public  _SPPow
  2006. ;_SPPow
  2007. ;     move.l  4(sp),d1
  2008. ;     move.l  12(sp),d0
  2009. ;     move.l  _MathTransBase,a6
  2010. ;     jmp     _LVOSPPow(a6)
  2011. ;
  2012. ;     public  _SPLog10
  2013. ;_SPLog10
  2014. ;     move.l  4(sp),d0
  2015. ;     move.l  _MathTransBase,a6
  2016. ;     jmp     _LVOSPLog10(a6)
  2017. ;
  2018. ;     public  _SPTieee
  2019. ;_SPTieee
  2020. ;     move.l  4(sp),d0
  2021. ;     move.l  _MathTransBase,a6
  2022. ;     jmp     _LVOSPTieee(a6)
  2023. ;
  2024. ;     public  _SPFieee
  2025. ;_SPFieee
  2026. ;     move.l  4(sp),d0
  2027. ;     move.l  _MathTransBase,a6
  2028. ;     jmp     _LVOSPFieee(a6)
  2029.  
  2030. #endasm
  2031.  
  2032.  
  2033. #if TIMING
  2034.  
  2035. PrintTime(what,start,finish)
  2036. char *what;
  2037. long *start,*finish;
  2038. {
  2039.   long dd;
  2040.   register long hh, mm, ss, xx;  /*** d4, d5, d6, d7 ***/
  2041.  
  2042.   if (start[2] > finish[2])   { finish[1]--;  finish[2] += 3000; }
  2043.   if (start[1] > finish[1])   { finish[0]--;  finish[1] += 1440; }
  2044.   dd=finish[0]-start[0]; mm=finish[1]-start[1]; xx=finish[2]-start[2];
  2045. #asm
  2046.     move.l    d5,d4    ; hh = mm/60
  2047.     divu    #60,d4
  2048.     ext.l    d4
  2049.     move.w    d4,d0    ; mm -= hh*60
  2050.     mulu    #60,d0
  2051.     sub.l    d0,d5
  2052.     move.l    d7,d6    ; ss = xx/50
  2053.     divu    #50,d6
  2054.     ext.l    d6
  2055.     move.w    d6,d0    ; xx -= ss*50
  2056.     mulu    #50,d0
  2057.     sub.l    d0,d7
  2058.     asl.l    #1,d7    ; xx *= 2
  2059. #endasm
  2060.   PrintF("%s: %ld-%02ld:%02ld:%02ld.%02ld\n",what,dd,hh,mm,ss,xx);
  2061. }
  2062.  
  2063. #endif
  2064.  
  2065.  
  2066. #if DEBUG
  2067.  
  2068. dump_screen_plot()
  2069. {
  2070.   register short plong,lat,elong;
  2071.   register long index;
  2072.   register short *toplot, *toget;
  2073.   long num;
  2074.   short firstx, firsty;
  2075.   short plot_buf[(SEGMENTS+1)*2];
  2076.   long file,_Open();
  2077.  
  2078.   if (!(file = _Open("ram:lines.dat",1006L)))  return;
  2079.  
  2080.   toplot = plot_buf;
  2081.  
  2082.   toget = e2d;
  2083.   firstx = DONT_PLOT;
  2084.   if ((toplot[num=0] = toget[0]) != DONT_PLOT) {
  2085.     firstx = toplot[0];  firsty = toplot[1] = toget[1];  num=2;
  2086.   }
  2087.   for (elong=2; elong<SEGMENTS*2; elong+=2)
  2088.     if ((toplot[num] = toget[elong]) != DONT_PLOT) {
  2089.       toplot[++num] = toget[elong+1];  num++;
  2090.     } else {
  2091.       if (num >= 4) {
  2092.     plot_dump(file,"EQUATOR",0,0,elong/2,num,toplot);
  2093.       }
  2094.       num = 0;
  2095.     }
  2096.   if (num >= 2  &&  firstx != DONT_PLOT) {
  2097.     toplot[num++] = firstx;  toplot[num++] = firsty;
  2098.   }
  2099.   if (num >= 4) {
  2100.     plot_dump(file,"EQUATOR",0,0,elong/2,num,toplot);
  2101.   }
  2102.  
  2103.   toget = p2d;
  2104.   firstx = DONT_PLOT;
  2105.   if ((toplot[num=0] = toget[0]) != DONT_PLOT) {
  2106.     firstx = toplot[0];  firsty = toplot[1] = toget[1];  num=2;
  2107.   }
  2108.   for (plong=2; plong<SEGMENTS*2; plong+=2)
  2109.     if ((toplot[num] = toget[plong]) != DONT_PLOT) {
  2110.       toplot[++num] = toget[plong+1];  num++;
  2111.     } else {
  2112.       if (num >= 4) {
  2113.     plot_dump(file,"POLAR RING",plong/2,0,0,num,toplot);
  2114.       }
  2115.       num = 0;
  2116.     }
  2117.   if (num >= 2  &&  firstx != DONT_PLOT) {
  2118.     toplot[num++] = firstx;  toplot[num++] = firsty;
  2119.   }
  2120.   if (num >= 4) {
  2121.     plot_dump(file,"POLAR RING",plong/2,0,0,num,toplot);
  2122.   }
  2123.  
  2124.   toget = x2d;
  2125.   for (lat=0; lat<LATRNG; lat++)
  2126.     for (elong=0; elong<SEGMENTS; elong++) {
  2127.       firstx = DONT_PLOT;
  2128.       if ((toplot[num=0] = toget[index=INDX(0,lat,elong)*2]) != DONT_PLOT) {
  2129.     firstx = toplot[0];  firsty = toplot[1] = toget[index+1];  num=2;
  2130.       }
  2131.       for (plong=1; plong<SEGMENTS; plong++)
  2132.     if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
  2133.       toplot[++num] = toget[index+1];  num++;
  2134.     } else {
  2135.       if (num >= 4) {
  2136.         plot_dump(file,"CIRCUMPOLAR",plong,lat+1,elong,num,toplot);
  2137.       }
  2138.       num = 0;
  2139.     }
  2140.       if (num >= 2  &&  firstx != DONT_PLOT) {
  2141.     toplot[num++] = firstx;  toplot[num++] = firsty;
  2142.       }
  2143.       if (num >= 4) {
  2144.     plot_dump(file,"CIRCUMPOLAR",plong,lat+1,elong,num,toplot);
  2145.       }
  2146.     }
  2147.  
  2148.   for (lat=0; lat<LATRNG; lat++)
  2149.     for (plong=0; plong<SEGMENTS; plong++) {
  2150.       firstx = DONT_PLOT;
  2151.       if ((toplot[num=0] = toget[index=INDX(plong,lat,0)*2]) != DONT_PLOT) {
  2152.     firstx = toplot[0];  firsty = toplot[1] = toget[index+1];  num=2;
  2153.       }
  2154.       for (elong=1; elong<SEGMENTS; elong++)
  2155.     if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
  2156.       toplot[++num] = toget[index+1];  num++;
  2157.     } else {
  2158.       if (num >= 4) {
  2159.         plot_dump(file,"CIRCUMEQUATORIAL",plong,lat+1,elong,num,toplot);
  2160.       }
  2161.       num = 0;
  2162.     }
  2163.       if (num >= 2  &&  firstx != DONT_PLOT) {
  2164.     toplot[num++] = firstx;  toplot[num++] = firsty;
  2165.       }
  2166.       if (num >= 4) {
  2167.     plot_dump(file,"CIRCUMEQUATORIAL",plong,lat+1,elong,num,toplot);
  2168.       }
  2169.     }
  2170.  
  2171.   for (elong=0; elong<SEGMENTS; elong++)
  2172.     for (plong=0; plong<SEGMENTS; plong++) {
  2173.       num = 0;
  2174.       if (!(elong&1))
  2175.     if ((toplot[0] = e2d[plong*2]) != DONT_PLOT) {
  2176.       toplot[1] = e2d[plong*2+1];  num=2;
  2177.     }
  2178.       for (lat=0; lat<LATRNG; lat++)
  2179.     if ((toplot[num]=toget[index=INDX(plong,lat,elong)*2])!=DONT_PLOT) {
  2180.       toplot[++num] = toget[index+1];  num++;
  2181.     } else {
  2182.       if (num >= 4) {
  2183.         plot_dump(file,"LONGITUDE LINES",plong,lat+1,elong,num,toplot);
  2184.       }
  2185.       num = 0;
  2186.     }
  2187.       if (!(plong&1))
  2188.     if ((toplot[num] = p2d[elong*2]) != DONT_PLOT) {
  2189.       toplot[++num] = p2d[elong*2+1];  num++;
  2190.     }
  2191.       if (num >= 4) {
  2192.     plot_dump(file,"LONGITUDE LINES",plong,lat+1,elong,num,toplot);
  2193.       }
  2194.     }
  2195.  
  2196.   _Close(file);
  2197. }
  2198.  
  2199.  
  2200. plot_dump(file,label,plong,lat,elong,num,toplot)
  2201. long file;
  2202. char *label;
  2203. short plong,lat,elong;
  2204. long num;
  2205. short *toplot;
  2206. {
  2207.   long i;
  2208.  
  2209.   FPrintF(file,"%s\nplong = %d  lat = %d  elong = %d  num = %ld\n",
  2210.     label,plong*INTERVAL,lat*INTERVAL,elong*INTERVAL,num);
  2211.   for (i=0; i < num; i+=2)
  2212.     FPrintF(file,"%5d\t%5d\n",toplot[i],toplot[i+1]);
  2213.   FPrintF(file,"\n");
  2214. }
  2215.  
  2216.  
  2217. dump_coordinates(all)
  2218. int all;
  2219. {
  2220.   short plong,lat,elong;
  2221.   long file, _Open();
  2222.  
  2223.   if (!(file = _Open("ram:coord.dat",1006L)))  return;
  2224.  
  2225.   for (plong=0; plong<SEGMENTS; plong++)
  2226.     for (lat=0; lat<LATRNG; lat++)
  2227.       for (elong=0; elong<SEGMENTS; elong++)
  2228.     if (all  ||  x2d[INDX(plong,lat,elong)*2+X] != DONT_PLOT)
  2229.       FPrintF(file,
  2230.        "x[%3d][%2d][%3d] = (%6d,%6d,%6d,%6d)   (%6d,%6d,%6d)   (%6d,%6d)\n",
  2231.         plong*INTERVAL, (lat+1)*INTERVAL, elong*INTERVAL,
  2232.         x4d[INDX(plong,lat,elong)*4+X], x4d[INDX(plong,lat,elong)*4+Y],
  2233.         x4d[INDX(plong,lat,elong)*4+Z], x4d[INDX(plong,lat,elong)*4+W],
  2234.         x3d[INDX(plong,lat,elong)*3+X], x3d[INDX(plong,lat,elong)*3+Y],
  2235.         x3d[INDX(plong,lat,elong)*3+Z],
  2236.         x2d[INDX(plong,lat,elong)*2+X], x2d[INDX(plong,lat,elong)*2+Y]);
  2237.  
  2238.   for (plong=0; plong<SEGMENTS; plong++)
  2239.     if (all  ||  p2d[plong*2+X] != DONT_PLOT)
  2240.       FPrintF(file, "p[%3d] = (%6d,%6d,%6d,%6d)   (%6d,%6d,%6d)   (%6d,%6d)\n",
  2241.     plong*INTERVAL,
  2242.     p4d[plong*4+X], p4d[plong*4+Y], p4d[plong*4+Z], p4d[plong*4+W],
  2243.     p3d[plong*3+X], p3d[plong*3+Y], p3d[plong*3+Z],
  2244.     p2d[plong*2+X], p2d[plong*2+Y]);
  2245.  
  2246.   for (elong=0; elong<SEGMENTS; elong++)
  2247.     if (all  ||  e2d[elong*2+X] != DONT_PLOT)
  2248.       FPrintF(file, "e[%3d] = (%6d,%6d,%6d,%6d)   (%6d,%6d,%6d)   (%6d,%6d)\n",
  2249.     elong*INTERVAL,
  2250.     e4d[elong*4+X], e4d[elong*4+Y], e4d[elong*4+Z], e4d[elong*4+W],
  2251.     e3d[elong*3+X], e3d[elong*3+Y], e3d[elong*3+Z],
  2252.     e2d[elong*2+X], e2d[elong*2+Y]);
  2253.  
  2254.   _Close(file);
  2255. }
  2256.  
  2257. #endif
  2258.  
  2259.  
  2260. #if TIMING | DEBUG
  2261.  
  2262. #asm
  2263. ;   FUNCTION                  IMPLEMENTATION
  2264. ; void PrintF(fmt_str,args...)          FPrintF(Output(),fmt_str,args...)
  2265. ; void FPrintF(fh,fmt_str,args...)
  2266. ;
  2267. ; These functions have no return value, unlike the standard 'C' versions
  2268. ;  that return the number of items matched in the format string.
  2269. ;
  2270. ; Note that PrintF and FPrintF use stack space for buffering the resulting
  2271. ;  string.  The length of the resulting string is set up below to be limited
  2272. ;  to < 256 characters.  If longer strings are needed, increase the buffer
  2273. ;  size (ResBuf), but beware of stack overflow when doing so.
  2274.  
  2275. ;Globals
  2276.     public    _SysBase,_DOSBase
  2277.     public    _LVORawDoFmt,_LVOWrite,_LVOOutput
  2278.  
  2279. ResBuf    equ    256
  2280.  
  2281.     public    _PrintF
  2282. _PrintF
  2283.     move.l    _DOSBase,a6    ; get file handle of current output
  2284.     jsr    _LVOOutput(a6)  ;   using Output()
  2285.     move.l    (sp),-(sp)      ; duplicate return address
  2286.     move.l    d0,4(sp)        ; put file handle "under" it
  2287.                 ; fall into FPrintF
  2288.  
  2289.     public    _FPrintF
  2290. _FPrintF
  2291.     movem.l a2/a3,-(sp)     ; don't need to save registers d0-3,a0-1,a6
  2292.  
  2293.     move.l    16(sp),a0       ; format string
  2294.     lea.l    20(sp),a1       ; data stream
  2295.     lea.l    put_char(pc),a2 ; output procedure called by RawDoFmt
  2296.  
  2297.     lea.l    -ResBuf(sp),sp  ; allocate some stack space where
  2298.     move.l    sp,a3        ;   put_ch will put characters from RawDoFmt
  2299.  
  2300.     move.l    _SysBase,a6    ; do the magic
  2301.     jsr    _LVORawDoFmt(a6) ;  using RawDoFmt()
  2302.  
  2303.     move.l    ResBuf+12(sp),d1 ; output file handle
  2304.     move.l    sp,d2        ; the result string is on the stack
  2305.     moveq    #0,d3
  2306.     move.w    str_len,d3    ; string length
  2307.     beq.s    1$        ; ignore a zero length string
  2308.  
  2309.     move.l    _DOSBase,a6    ; output the results
  2310.     jsr    _LVOWrite(a6)   ;   using Write()
  2311.  
  2312. 1$    move.w    #-1,str_len    ; reset for next time
  2313.     lea.l    ResBuf(sp),sp   ; release stack space
  2314.     movem.l (sp)+,a2/a3     ; restore registers
  2315.     rts            ; all done
  2316.  
  2317.  
  2318.     ; length of the output string minus the terminating null
  2319.     dseg
  2320.     public str_len
  2321. str_len dc.w -1
  2322.     cseg
  2323.  
  2324.     far data
  2325. put_char
  2326.     addq.w    #1,str_len    ; add 1 to string length
  2327.     near data
  2328.     move.b    d0,(a3)+        ; this "procedure" stuffs the characters from
  2329.     rts            ;  RawDoFmt into the destination buffer
  2330.  
  2331. #endasm
  2332.  
  2333. #endif
  2334.